v2 (Eric): - use ARRAY_SIZE - re-use 'image_destroy' for cleaning up after failure - check directly the region pointer instead of the buffer object when determining if a region exists
v3 (Chad): - do not duplicate an image without any valid planes - do not refactor region setting for multiple fds - record the offsets (and strides) also when planes are in separate buffers - use the region count utility instead of always iterating through the entire array Signed-off-by: Topi Pohjolainen <topi.pohjolai...@intel.com> --- src/mesa/drivers/dri/intel/intel_screen.c | 58 +++++++++++++++++++++---------- 1 file changed, 40 insertions(+), 18 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 57c8417..e8ed622 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -491,8 +491,18 @@ intel_create_image_from_texture(__DRIcontext *context, int target, static void intel_destroy_image(__DRIimage *image) { - intel_region_release(&image->regions[0]); - free(image); + int i; + + for (i = 0; i < intel_image_get_region_count(image); ++i) { + /** + * Failures during creation are cleaned up here and hence not all the + * regions may not be valid. + */ + if (image->regions[i]) + intel_region_release(&image->regions[i]); + } + + free(image); } static __DRIimage * @@ -569,16 +579,23 @@ intel_query_image(__DRIimage *image, int attrib, int *value) static __DRIimage * intel_dup_image(__DRIimage *orig_image, void *loaderPrivate) { + int i; __DRIimage *image; + /* There needs to be at least one plane per image. */ + if (!orig_image->regions[0]) + return NULL; + image = calloc(1, sizeof *image); if (image == NULL) return NULL; - intel_region_reference(&image->regions[0], orig_image->regions[0]); - if (image->regions[0] == NULL) { - free(image); - return NULL; + for (i = 0; i < intel_image_get_region_count(orig_image); ++i) { + intel_region_reference(&image->regions[i], orig_image->regions[i]); + if (image->regions[i] == NULL) { + intel_destroy_image(image); + return NULL; + } } image->internal_format = orig_image->internal_format; @@ -653,15 +670,15 @@ intel_create_image_from_fds(__DRIscreen *screen, void *loaderPrivate) { struct intel_screen *intelScreen = screen->driverPrivate; - struct intel_image_format *f; + struct intel_image_format *f = intel_image_format_lookup(fourcc); __DRIimage *image; int i, index; - if (fds == NULL || num_fds != 1) - return NULL; - - f = intel_image_format_lookup(fourcc); - if (f == NULL) + /** + * In case the image is to consist of multiple regions, there must be exactly + * one region per plane. + */ + if (fds == NULL || f == NULL || (num_fds > 1 && f->nplanes != num_fds)) return NULL; if (f->nplanes == 1) @@ -672,12 +689,17 @@ intel_create_image_from_fds(__DRIscreen *screen, if (image == NULL) return NULL; - image->regions[0] = intel_region_alloc_for_fd(intelScreen, - 1, width, height, - strides[0], fds[0], "image"); - if (image->regions[0] == NULL) { - free(image); - return NULL; + for (i = 0; i < num_fds; i++) { + image->regions[i] = intel_region_alloc_for_fd( + intelScreen, f->planes[i].cpp, + width >> f->planes[i].width_shift, + height >> f->planes[i].height_shift, + strides[i], fds[i], "image"); + + if (image->regions[i] == NULL) { + intel_destroy_image(image); + return NULL; + } } image->planar_format = f; -- 1.8.1.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev