diff --git a/src/gbm/backends/dri/gbm_dri.c b/src/gbm/backends/dri/gbm_dri.c index 4d915a35a5a..0526f4f8dc1 100644 --- a/src/gbm/backends/dri/gbm_dri.c +++ b/src/gbm/backends/dri/gbm_dri.c @@ -942,6 +942,9 @@ gbm_dri_bo_create(struct gbm_device *gbm, struct gbm_dri_bo *bo; int dri_format; unsigned dri_use = 0; + uint64_t *mods_comp = NULL; + uint64_t *mods_filtered = NULL; + unsigned int count_filtered = 0; format = gbm_core.v0.format_canonicalize(format); @@ -982,12 +985,98 @@ gbm_dri_bo_create(struct gbm_device *gbm, goto failed; } + /* If the driver supports fixed-rate compression, filter the acceptable + * modifiers by the compression rate. */ + if (modifiers && dri->image->queryCompressionModifiers) { + enum __DRIFixedRateCompression comp = __DRI_FIXED_RATE_COMPRESSION_NONE; + + switch (usage & GBM_BO_FIXED_COMPRESSION_MASK) { +#define CASE(x) case GBM_BO_FIXED_COMPRESSION_ ## x: comp = __DRI_FIXED_RATE_COMPRESSION_ ## x; break; + CASE(DEFAULT); + CASE(1BPC); + CASE(2BPC); + CASE(3BPC); + CASE(4BPC); + CASE(5BPC); + CASE(6BPC); + CASE(7BPC); + CASE(8BPC); + CASE(9BPC); + CASE(10BPC); + CASE(11BPC); + CASE(12BPC); +#undef CASE + default: + break; + } + + int count_comp = 0; + + /* Find how many acceptable modifiers there are for our rate. If there + * are none, fall back to no compression, as it is not mandatory to use + * the specified compression rate. */ + if (!dri->image->queryCompressionModifiers(dri->screen, format, comp, + 0, NULL, &count_comp) || + count_comp == 0) { + if (comp == __DRI_FIXED_RATE_COMPRESSION_NONE) { + errno = EINVAL; + goto failed; + } + + comp = __DRI_FIXED_RATE_COMPRESSION_NONE; + if (!dri->image->queryCompressionModifiers(dri->screen, format, comp, + 0, NULL, &count_comp)) { + errno = EINVAL; + goto failed; + } + } + + if (count_comp == 0) { + errno = EINVAL; + goto failed; + } + + mods_comp = malloc(count_comp * sizeof(uint64_t)); + mods_filtered = malloc(count_comp * sizeof(uint64_t)); + if (!mods_comp || !mods_filtered) { + errno = ENOMEM; + goto failed; + } + + if (!dri->image->queryCompressionModifiers(dri->screen, format, comp, + count_comp, mods_comp, + &count_comp)) { + errno = ENOMEM; + goto failed; + } + + + /* Intersect the list of user-supplied acceptable modifiers with the set + * of modifiers acceptable for this compression rate. */ + for (unsigned int i = 0; i < count_comp; i++) { + for (unsigned int j = 0; j < count; j++) { + if (mods_comp[i] == modifiers[j]) { + mods_filtered[count_filtered++] = mods_comp[i]; + break; + } + } + } + + free(mods_comp); + mods_comp = NULL; + } + bo->image = loader_dri_create_image(dri->screen, dri->image, width, height, - dri_format, dri_use, modifiers, count, + dri_format, dri_use, + mods_filtered ? mods_filtered : modifiers, + mods_filtered ? count_filtered : count, bo); if (bo->image == NULL) goto failed; + free(mods_filtered); + mods_filtered = NULL; + if (modifiers) assert(gbm_dri_bo_get_modifier(&bo->base) != DRM_FORMAT_MOD_INVALID); @@ -999,6 +1088,8 @@ gbm_dri_bo_create(struct gbm_device *gbm, return &bo->base; failed: + free(mods_comp); + free(mods_filtered); free(bo); return NULL; } diff --git a/src/gbm/main/gbm.h b/src/gbm/main/gbm.h index 1a1e2caecb4..9c680f65b95 100644 --- a/src/gbm/main/gbm.h +++ b/src/gbm/main/gbm.h @@ -264,8 +264,77 @@ enum gbm_bo_flags { * with pixel data. */ GBM_BO_USE_FRONT_RENDERING = (1 << 6), + + /** + * Allow the driver to select fixed-rate compression parameters. + */ + GBM_BO_FIXED_COMPRESSION_DEFAULT = (1 << 7), + + /** + * Fixed-rate compression: at least 1bpc, less than 2bpc + */ + GBM_BO_FIXED_COMPRESSION_1BPC = (2 << 7), + + /** + * Fixed-rate compression: at least 2bpc, less than 3bpc + */ + GBM_BO_FIXED_COMPRESSION_2BPC = (3 << 7), + + /** + * Fixed-rate compression: at least 3bpc, less than 4bpc + */ + GBM_BO_FIXED_COMPRESSION_3BPC = (4 << 7), + + /** + * Fixed-rate compression: at least 4bpc, less than 5bpc + */ + GBM_BO_FIXED_COMPRESSION_4BPC = (5 << 7), + + /** + * Fixed-rate compression: at least 5bpc, less than 6bpc + */ + GBM_BO_FIXED_COMPRESSION_5BPC = (6 << 7), + + /** + * Fixed-rate compression: at least 6bpc, less than 7bpc + */ + GBM_BO_FIXED_COMPRESSION_6BPC = (7 << 7), + + /** + * Fixed-rate compression: at least 7bpc, less than 8bpc + */ + GBM_BO_FIXED_COMPRESSION_7BPC = (8 << 7), + + /** + * Fixed-rate compression: at least 8bpc, less than 9bpc + */ + GBM_BO_FIXED_COMPRESSION_8BPC = (9 << 7), + + /** + * Fixed-rate compression: at least 9bpc, less than 10bpc + */ + GBM_BO_FIXED_COMPRESSION_9BPC = (10 << 7), + + /** + * Fixed-rate compression: at least 10bpc, less than 11bpc + */ + GBM_BO_FIXED_COMPRESSION_10BPC = (11 << 7), + + /** + * Fixed-rate compression: at least 11bpc, less than 12bpc + */ + GBM_BO_FIXED_COMPRESSION_11BPC = (12 << 7), + + /** + * Fixed-rate compression: at least 12bpc, no maximum rate + */ + GBM_BO_FIXED_COMPRESSION_12BPC = (13 << 7), + + /* next available value is (1 << 11) */ }; +#define GBM_BO_FIXED_COMPRESSION_MASK (((1 << 11) - 1) & ~((1 << 7) - 1)) + int gbm_device_get_fd(struct gbm_device *gbm);