v2 (as advised by 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
Signed-off-by: Topi Pohjolainen <topi.pohjolai...@intel.com> --- src/mesa/drivers/dri/intel/intel_screen.c | 103 +++++++++++++++++++++--------- 1 file changed, 72 insertions(+), 31 deletions(-) diff --git a/src/mesa/drivers/dri/intel/intel_screen.c b/src/mesa/drivers/dri/intel/intel_screen.c index 4973441..d822b1c 100644 --- a/src/mesa/drivers/dri/intel/intel_screen.c +++ b/src/mesa/drivers/dri/intel/intel_screen.c @@ -490,8 +490,14 @@ 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 < ARRAY_SIZE(image->regions); ++i) { + if (image->regions[i]) + intel_region_release(&image->regions[i]); + } + + free(image); } static __DRIimage * @@ -568,16 +574,22 @@ intel_query_image(__DRIimage *image, int attrib, int *value) static __DRIimage * intel_dup_image(__DRIimage *orig_image, void *loaderPrivate) { + int i; __DRIimage *image; 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 < ARRAY_SIZE(image->regions); ++i) { + if (!orig_image->regions[i]) + break; + + 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; @@ -646,47 +658,76 @@ intel_create_image_from_names(__DRIscreen *screen, } static __DRIimage * +intel_setup_image_from_fds(struct intel_screen *screen, int width, int height, + const struct intel_image_format *f, + const int *fds, int num_fds, const int *strides, + void *loaderPriv) +{ + int i; + __DRIimage *img; + + if (f->nplanes == 1) + img = intel_allocate_image(f->planes[0].dri_format, loaderPriv); + else + img = intel_allocate_image(__DRI_IMAGE_FORMAT_NONE, loaderPriv); + + if (img == NULL) + return NULL; + + for (i = 0; i < num_fds; i++) { + img->regions[i] = intel_region_alloc_for_fd(screen, f->planes[i].cpp, + width >> f->planes[i].width_shift, + height >> f->planes[i].height_shift, + strides[i], fds[i], "image"); + + if (img->regions[i] == NULL) { + intel_destroy_image(img); + return NULL; + } + } + + intel_setup_image_from_dimensions(img); + + return img; +} + +static __DRIimage * intel_create_image_from_fds(__DRIscreen *screen, int width, int height, int fourcc, int *fds, int num_fds, int *strides, int *offsets, 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) - image = intel_allocate_image(f->planes[0].dri_format, loaderPriv); - else - image = intel_allocate_image(__DRI_IMAGE_FORMAT_NONE, loaderPriv); - + image = intel_setup_image_from_fds(intelScreen, width, height, f, + fds, num_fds, strides, loaderPrivate); 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; - } - image->planar_format = f; - for (i = 0; i < f->nplanes; i++) { - index = f->planes[i].buffer_index; - image->offsets[index] = offsets[index]; - image->strides[index] = strides[index]; - } - intel_setup_image_from_dimensions(image); + /** + * In case the image is to consist of multiple planes all in the same region, + * one needs to record not only the invidual strides, but also the locations + * of the planes within the region. + */ + if (num_fds == 1 && f->nplanes > 1) { + for (i = 0; i < f->nplanes; i++) { + index = f->planes[i].buffer_index; + image->offsets[index] = offsets[index]; + image->strides[index] = strides[index]; + } + } return image; } -- 1.8.1.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev