<div dir="ltr"><div class="gmail_extra"><div class="gmail_quote">On Mon, Mar 13, 2017 at 10:24 PM, Ben Widawsky <span dir="ltr"><<a href="mailto:ben@bwidawsk.net" target="_blank">ben@bwidawsk.net</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">The idea behind modifiers like this is that the user of GBM will have<br>
some mechanism to query what properties the hardware supports for its BO<br>
or surface. This information is directly passed in (and stored) so that<br>
the DRI implementation can create an image with the appropriate<br>
attributes.<br>
<br>
A getter() will be added later so that the user GBM will be able to<br>
query what modifier should be used.<br>
<br>
Only in surface creation, the modifiers are stored until the BO is<br>
actually allocated. In regular buffer allocation, the correct modifier<br>
can (will be, in future patches be chosen at creation time.<br>
<br>
v2: Make sure to check if count is non-zero in addition to testing if<br>
calloc fails. (Daniel)<br>
<br>
v3: Remove "usage" and "flags" from modifier creation. Requested by<br>
Kristian.<br>
<br>
v4: Take advantage of the "INVALID" modifier added by the GET_PLANE2<br>
series.<br>
<br>
v5: Don't bother with storing modifiers for gbm_bo_create because that's<br>
a synchronous operation and we can actually select the correct modifier<br>
at create time (done in a later patch) (Jason)<br>
<br>
Cc: Kristian Høgsberg <<a href="mailto:krh@bitplanet.net">krh@bitplanet.net</a>><br>
Cc: Jason Ekstrand <<a href="mailto:jason@jlekstrand.net">jason@jlekstrand.net</a>><br>
References (v4): <a href="https://lists.freedesktop.org/archives/intel-gfx/2017-January/116636.html" rel="noreferrer" target="_blank">https://lists.freedesktop.org/<wbr>archives/intel-gfx/2017-<wbr>January/116636.html</a><br>
Signed-off-by: Ben Widawsky <<a href="mailto:ben@bwidawsk.net">ben@bwidawsk.net</a>><br>
Reviewed-by: Eric Engestrom <<a href="mailto:eric.engestrom@imgtec.com">eric.engestrom@imgtec.com</a>> (v1)<br>
Acked-by: Daniel Stone <<a href="mailto:daniels@collabora.com">daniels@collabora.com</a>><br>
---<br>
</div></div> src/gbm/backends/dri/gbm_dri.c | 62 ++++++++++++++++++++++++++++++<wbr>++++++------<br>
src/gbm/gbm-symbols-check | 2 ++<br>
src/gbm/main/gbm.c | 39 ++++++++++++++++++++++++--<br>
src/gbm/main/gbm.h | 12 ++++++++<br>
src/gbm/main/gbmint.h | 12 ++++++--<br>
5 files changed, 115 insertions(+), 12 deletions(-)<br>
<br>
diff --git a/src/gbm/backends/dri/gbm_<wbr>dri.c b/src/gbm/backends/dri/gbm_<wbr>dri.c<br>
index 7106dc1229..1224ce4476 100644<br>
<span class="">--- a/src/gbm/backends/dri/gbm_<wbr>dri.c<br>
+++ b/src/gbm/backends/dri/gbm_<wbr>dri.c<br>
@@ -1023,13 +1023,20 @@ free_bo:<br>
static struct gbm_bo *<br>
gbm_dri_bo_create(struct gbm_device *gbm,<br>
uint32_t width, uint32_t height,<br>
- uint32_t format, uint32_t usage)<br>
+ uint32_t format, uint32_t usage,<br>
+ const uint64_t *modifiers,<br>
+ const unsigned int count)<br>
{<br>
struct gbm_dri_device *dri = gbm_dri_device(gbm);<br>
struct gbm_dri_bo *bo;<br>
int dri_format;<br>
unsigned dri_use = 0;<br>
<br>
+ /* Callers of this may specify a modifier, or a dri usage, but not both. The<br>
+ * newer modifier interface deprecates the older usage flags.<br>
+ */<br>
+ assert(!(usage && count));<br>
+<br>
</span><span class=""> if (usage & GBM_BO_USE_WRITE || dri->image == NULL)<br>
return create_dumb(gbm, width, height, format, usage);<br>
<br>
</span>@@ -1087,11 +1094,24 @@ gbm_dri_bo_create(struct gbm_device *gbm,<br>
<span class=""> /* Gallium drivers requires shared in order to get the handle/stride */<br>
dri_use |= __DRI_IMAGE_USE_SHARE;<br>
<br>
- bo->image =<br>
- dri->image->createImage(dri-><wbr>screen,<br>
- width, height,<br>
- dri_format, dri_use,<br>
- bo);<br>
+ if (!dri->image || dri->image->base.version < 14 ||<br>
+ !dri->image-><wbr>createImageWithModifiers) {<br>
+ if (modifiers) {<br></span></blockquote><div><br></div><div>This logic still isn't correct. As written, it will always call createImageWithModifiers if it's available even if no modifiers are provided. I think you want the "if (modifiers)" to be the outside bit of control-flow<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
+ fprintf(stderr, "Modifiers specified, but DRI is too old\n");<br>
</span>+ errno = ENOSYS;<br>
+ goto failed;<br>
+ }<br>
<span class="">+<br>
+ bo->image = dri->image->createImage(dri-><wbr>screen, width, height,<br>
+ dri_format, dri_use, bo);<br>
</span><span class="">+ } else {<br>
+ bo->image =<br>
+ dri->image-><wbr>createImageWithModifiers(dri-><wbr>screen,<br>
+ width, height,<br>
+ dri_format,<br>
+ modifiers, count,<br>
+ bo);<br>
+ }<br>
if (bo->image == NULL)<br>
goto failed;<br>
<br>
</span>@@ -1165,19 +1185,44 @@ gbm_dri_bo_unmap(struct gbm_bo *_bo, void *map_data)<br>
static struct gbm_surface *<br>
gbm_dri_surface_create(struct gbm_device *gbm,<br>
uint32_t width, uint32_t height,<br>
- uint32_t format, uint32_t flags)<br>
<span class="">+ uint32_t format, uint32_t flags,<br>
+ const uint64_t *modifiers, const unsigned count)<br>
{<br>
</span>+ struct gbm_dri_device *dri = gbm_dri_device(gbm);<br>
struct gbm_dri_surface *surf;<br>
<br>
+ if (modifiers &&<br>
+ (!dri->image || dri->image->base.version < 14 ||<br>
+ !dri->image-><wbr>createImageWithModifiers)) {<br>
+ errno = ENOSYS;<br>
<span class="">+ return NULL;<br>
+ }<br>
+<br>
</span> surf = calloc(1, sizeof *surf);<br>
- if (surf == NULL)<br>
+ if (surf == NULL) {<br>
+ errno = ENOMEM;<br>
return NULL;<br>
+ }<br>
<br>
surf->base.gbm = gbm;<br>
surf->base.width = width;<br>
surf->base.height = height;<br>
<span class=""> surf->base.format = format;<br>
surf->base.flags = flags;<br>
</span>+ if (!modifiers) {<br>
+ assert(!count);<br>
+ return &surf->base;<br>
+ }<br>
+<br>
<span class="">+ surf->base.modifiers = calloc(count, sizeof(*modifiers));<br>
+ if (count && !surf->base.modifiers) {<br>
</span>+ errno = ENOMEM;<br>
+ free(surf);<br>
<span class="">+ return NULL;<br>
+ }<br>
+<br>
</span><span class="">+ surf->base.count = count;<br>
+ memcpy(surf->base.modifiers, modifiers, count * sizeof(*modifiers));<br>
<br>
</span> return &surf->base;<br>
}<br>
@@ -1187,6 +1232,7 @@ gbm_dri_surface_destroy(struct gbm_surface *_surf)<br>
<span class=""> {<br>
struct gbm_dri_surface *surf = gbm_dri_surface(_surf);<br>
<br>
+ free(surf->base.modifiers);<br>
free(surf);<br>
}<br>
<br>
diff --git a/src/gbm/gbm-symbols-check b/src/gbm/gbm-symbols-check<br>
</span>index 81da1e0793..0550baddc4 100755<br>
<span class="">--- a/src/gbm/gbm-symbols-check<br>
+++ b/src/gbm/gbm-symbols-check<br>
@@ -8,6 +8,7 @@ gbm_device_is_format_supported<br>
gbm_device_destroy<br>
gbm_create_device<br>
gbm_bo_create<br>
+gbm_bo_create_with_modifiers<br>
gbm_bo_import<br>
gbm_bo_map<br>
gbm_bo_unmap<br>
@@ -27,6 +28,7 @@ gbm_bo_set_user_data<br>
gbm_bo_get_user_data<br>
gbm_bo_destroy<br>
gbm_surface_create<br>
+gbm_surface_create_with_<wbr>modifiers<br>
gbm_surface_needs_lock_front_<wbr>buffer<br>
gbm_surface_lock_front_buffer<br>
gbm_surface_release_buffer<br>
diff --git a/src/gbm/main/gbm.c b/src/gbm/main/gbm.c<br>
</span>index afcca63da3..7bacd8b86a 100644<br>
--- a/src/gbm/main/gbm.c<br>
+++ b/src/gbm/main/gbm.c<br>
@@ -369,9 +369,28 @@ gbm_bo_create(struct gbm_device *gbm,<br>
<span class=""> return NULL;<br>
}<br>
<br>
- return gbm->bo_create(gbm, width, height, format, usage);<br>
+ return gbm->bo_create(gbm, width, height, format, usage, NULL, 0);<br>
}<br>
<br>
</span><span class="">+GBM_EXPORT struct gbm_bo *<br>
+gbm_bo_create_with_modifiers(<wbr>struct gbm_device *gbm,<br>
+ uint32_t width, uint32_t height,<br>
+ uint32_t format,<br>
+ const uint64_t *modifiers,<br>
+ const unsigned int count)<br>
+{<br>
+ if (width == 0 || height == 0) {<br>
+ errno = EINVAL;<br>
+ return NULL;<br>
+ }<br>
+<br>
</span>+ if ((count && !modifiers) || (modifiers && !count)) {<br>
<span class="">+ errno = EINVAL;<br>
+ return NULL;<br>
+ }<br></span></blockquote><div><br></div><div>Is modifiers == NULL ever allowed? If so, what does it mean? If the current mechanism is going to work, modifiers == NULL needs to have exactly the same meaning as flags == 0.<br></div><div> </div><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">
+<br>
</span><span class="">+ return gbm->bo_create(gbm, width, height, format, 0, modifiers, count);<br>
+}<br>
/**<br>
* Create a gbm buffer object from an foreign object<br>
*<br>
</span>@@ -477,7 +496,23 @@ gbm_surface_create(struct gbm_device *gbm,<br>
uint32_t width, uint32_t height,<br>
<span class=""> uint32_t format, uint32_t flags)<br>
{<br>
- return gbm->surface_create(gbm, width, height, format, flags);<br>
+ return gbm->surface_create(gbm, width, height, format, flags, NULL, 0);<br>
+}<br>
+<br>
</span><span class="">+GBM_EXPORT struct gbm_surface *<br>
+gbm_surface_create_with_<wbr>modifiers(struct gbm_device *gbm,<br>
+ uint32_t width, uint32_t height,<br>
+ uint32_t format,<br>
+ const uint64_t *modifiers,<br>
+ const unsigned int count)<br>
+{<br>
</span>+ if ((count && !modifiers) || (modifiers && !count)) {<br>
<span class="">+ errno = EINVAL;<br>
+ return NULL;<br>
+ }<br>
+<br>
</span><span class="">+ return gbm->surface_create(gbm, width, height, format, 0,<br>
+ modifiers, count);<br>
}<br>
<br>
/**<br>
diff --git a/src/gbm/main/gbm.h b/src/gbm/main/gbm.h<br>
index e3e5d34d97..5f588dab58 100644<br>
--- a/src/gbm/main/gbm.h<br>
+++ b/src/gbm/main/gbm.h<br>
</span>@@ -243,6 +243,12 @@ gbm_bo_create(struct gbm_device *gbm,<br>
uint32_t width, uint32_t height,<br>
uint32_t format, uint32_t flags);<br>
<br>
+struct gbm_bo *<br>
<span class="">+gbm_bo_create_with_modifiers(<wbr>struct gbm_device *gbm,<br>
+ uint32_t width, uint32_t height,<br>
+ uint32_t format,<br>
+ const uint64_t *modifiers,<br>
</span>+ const unsigned int count);<br>
<span class=""> #define GBM_BO_IMPORT_WL_BUFFER 0x5501<br>
#define GBM_BO_IMPORT_EGL_IMAGE 0x5502<br>
#define GBM_BO_IMPORT_FD 0x5503<br>
</span>@@ -345,6 +351,12 @@ gbm_surface_create(struct gbm_device *gbm,<br>
uint32_t width, uint32_t height,<br>
uint32_t format, uint32_t flags);<br>
<br>
+struct gbm_surface *<br>
<span class="">+gbm_surface_create_with_<wbr>modifiers(struct gbm_device *gbm,<br>
+ uint32_t width, uint32_t height,<br>
+ uint32_t format,<br>
+ const uint64_t *modifiers,<br>
</span>+ const unsigned int count);<br>
<span class=""> int<br>
gbm_surface_needs_lock_front_<wbr>buffer(struct gbm_surface *surface);<br>
<br>
diff --git a/src/gbm/main/gbmint.h b/src/gbm/main/gbmint.h<br>
index a6541d91c5..d8c9f6e5d7 100644<br>
--- a/src/gbm/main/gbmint.h<br>
+++ b/src/gbm/main/gbmint.h<br>
@@ -65,7 +65,9 @@ struct gbm_device {<br>
</span> struct gbm_bo *(*bo_create)(struct gbm_device *gbm,<br>
uint32_t width, uint32_t height,<br>
<span class=""> uint32_t format,<br>
- uint32_t usage);<br>
</span>+ uint32_t usage,<br>
<span class="">+ const uint64_t *modifiers,<br>
+ const unsigned int count);<br>
</span><span class=""> struct gbm_bo *(*bo_import)(struct gbm_device *gbm, uint32_t type,<br>
void *buffer, uint32_t usage);<br>
void *(*bo_map)(struct gbm_bo *bo,<br>
@@ -84,7 +86,9 @@ struct gbm_device {<br>
<br>
</span> struct gbm_surface *(*surface_create)(struct gbm_device *gbm,<br>
uint32_t width, uint32_t height,<br>
- uint32_t format, uint32_t flags);<br>
<span class="">+ uint32_t format, uint32_t flags,<br>
</span>+ const uint64_t *modifiers,<br>
+ const unsigned count);<br>
<div class="HOEnZb"><div class="h5"> struct gbm_bo *(*surface_lock_front_buffer)(<wbr>struct gbm_surface *surface);<br>
void (*surface_release_buffer)(<wbr>struct gbm_surface *surface,<br>
struct gbm_bo *bo);<br>
@@ -114,6 +118,10 @@ struct gbm_surface {<br>
uint32_t height;<br>
uint32_t format;<br>
uint32_t flags;<br>
+ struct {<br>
+ uint64_t *modifiers;<br>
+ unsigned count;<br>
+ };<br>
};<br>
<br>
struct gbm_backend {<br>
</div></div><span class="HOEnZb"><font color="#888888">--<br>
2.12.0<br>
<br>
</font></span></blockquote></div><br></div></div>