17ec681f3Smrg/* 27ec681f3Smrg * Mesa 3-D graphics library 37ec681f3Smrg * 47ec681f3Smrg * Copyright 2009, VMware, Inc. 57ec681f3Smrg * All Rights Reserved. 67ec681f3Smrg * Copyright (C) 2010 LunarG Inc. 77ec681f3Smrg * 87ec681f3Smrg * Permission is hereby granted, free of charge, to any person obtaining a 97ec681f3Smrg * copy of this software and associated documentation files (the "Software"), 107ec681f3Smrg * to deal in the Software without restriction, including without limitation 117ec681f3Smrg * the rights to use, copy, modify, merge, publish, distribute, sublicense, 127ec681f3Smrg * and/or sell copies of the Software, and to permit persons to whom the 137ec681f3Smrg * Software is furnished to do so, subject to the following conditions: 147ec681f3Smrg * 157ec681f3Smrg * The above copyright notice and this permission notice shall be included 167ec681f3Smrg * in all copies or substantial portions of the Software. 177ec681f3Smrg * 187ec681f3Smrg * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 197ec681f3Smrg * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 207ec681f3Smrg * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 217ec681f3Smrg * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 227ec681f3Smrg * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 237ec681f3Smrg * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 247ec681f3Smrg * OTHER DEALINGS IN THE SOFTWARE. 257ec681f3Smrg * 267ec681f3Smrg * Authors: 277ec681f3Smrg * Keith Whitwell <keithw@vmware.com> Jakob Bornecrantz 287ec681f3Smrg * <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com> 297ec681f3Smrg */ 307ec681f3Smrg 317ec681f3Smrg#include <xf86drm.h> 327ec681f3Smrg#include "GL/mesa_glinterop.h" 337ec681f3Smrg#include "util/disk_cache.h" 347ec681f3Smrg#include "util/u_memory.h" 357ec681f3Smrg#include "util/u_inlines.h" 367ec681f3Smrg#include "util/format/u_format.h" 377ec681f3Smrg#include "util/u_debug.h" 387ec681f3Smrg#include "frontend/drm_driver.h" 397ec681f3Smrg#include "state_tracker/st_cb_bufferobjects.h" 407ec681f3Smrg#include "state_tracker/st_cb_fbo.h" 417ec681f3Smrg#include "state_tracker/st_cb_texture.h" 427ec681f3Smrg#include "state_tracker/st_texture.h" 437ec681f3Smrg#include "state_tracker/st_context.h" 447ec681f3Smrg#include "pipe-loader/pipe_loader.h" 457ec681f3Smrg#include "main/bufferobj.h" 467ec681f3Smrg#include "main/texobj.h" 477ec681f3Smrg 487ec681f3Smrg#include "dri_util.h" 497ec681f3Smrg 507ec681f3Smrg#include "dri_helpers.h" 517ec681f3Smrg#include "dri_drawable.h" 527ec681f3Smrg#include "dri_query_renderer.h" 537ec681f3Smrg 547ec681f3Smrg#include "drm-uapi/drm_fourcc.h" 557ec681f3Smrg 567ec681f3Smrgstruct dri2_buffer 577ec681f3Smrg{ 587ec681f3Smrg __DRIbuffer base; 597ec681f3Smrg struct pipe_resource *resource; 607ec681f3Smrg}; 617ec681f3Smrg 627ec681f3Smrgstatic inline struct dri2_buffer * 637ec681f3Smrgdri2_buffer(__DRIbuffer * driBufferPriv) 647ec681f3Smrg{ 657ec681f3Smrg return (struct dri2_buffer *) driBufferPriv; 667ec681f3Smrg} 677ec681f3Smrg 687ec681f3Smrg/** 697ec681f3Smrg * DRI2 flush extension. 707ec681f3Smrg */ 717ec681f3Smrgstatic void 727ec681f3Smrgdri2_flush_drawable(__DRIdrawable *dPriv) 737ec681f3Smrg{ 747ec681f3Smrg dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1); 757ec681f3Smrg} 767ec681f3Smrg 777ec681f3Smrgstatic void 787ec681f3Smrgdri2_invalidate_drawable(__DRIdrawable *dPriv) 797ec681f3Smrg{ 807ec681f3Smrg struct dri_drawable *drawable = dri_drawable(dPriv); 817ec681f3Smrg 827ec681f3Smrg dri2InvalidateDrawable(dPriv); 837ec681f3Smrg drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; 847ec681f3Smrg drawable->texture_mask = 0; 857ec681f3Smrg 867ec681f3Smrg p_atomic_inc(&drawable->base.stamp); 877ec681f3Smrg} 887ec681f3Smrg 897ec681f3Smrgstatic const __DRI2flushExtension dri2FlushExtension = { 907ec681f3Smrg .base = { __DRI2_FLUSH, 4 }, 917ec681f3Smrg 927ec681f3Smrg .flush = dri2_flush_drawable, 937ec681f3Smrg .invalidate = dri2_invalidate_drawable, 947ec681f3Smrg .flush_with_flags = dri_flush, 957ec681f3Smrg}; 967ec681f3Smrg 977ec681f3Smrg/** 987ec681f3Smrg * Retrieve __DRIbuffer from the DRI loader. 997ec681f3Smrg */ 1007ec681f3Smrgstatic __DRIbuffer * 1017ec681f3Smrgdri2_drawable_get_buffers(struct dri_drawable *drawable, 1027ec681f3Smrg const enum st_attachment_type *atts, 1037ec681f3Smrg unsigned *count) 1047ec681f3Smrg{ 1057ec681f3Smrg __DRIdrawable *dri_drawable = drawable->dPriv; 1067ec681f3Smrg const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; 1077ec681f3Smrg boolean with_format; 1087ec681f3Smrg __DRIbuffer *buffers; 1097ec681f3Smrg int num_buffers; 1107ec681f3Smrg unsigned attachments[__DRI_BUFFER_COUNT]; 1117ec681f3Smrg unsigned num_attachments, i; 1127ec681f3Smrg 1137ec681f3Smrg assert(loader); 1147ec681f3Smrg assert(*count <= __DRI_BUFFER_COUNT); 1157ec681f3Smrg with_format = dri_with_format(drawable->sPriv); 1167ec681f3Smrg 1177ec681f3Smrg num_attachments = 0; 1187ec681f3Smrg 1197ec681f3Smrg /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ 1207ec681f3Smrg if (!with_format) 1217ec681f3Smrg attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; 1227ec681f3Smrg 1237ec681f3Smrg for (i = 0; i < *count; i++) { 1247ec681f3Smrg enum pipe_format format; 1257ec681f3Smrg unsigned bind; 1267ec681f3Smrg int att, depth; 1277ec681f3Smrg 1287ec681f3Smrg dri_drawable_get_format(drawable, atts[i], &format, &bind); 1297ec681f3Smrg if (format == PIPE_FORMAT_NONE) 1307ec681f3Smrg continue; 1317ec681f3Smrg 1327ec681f3Smrg switch (atts[i]) { 1337ec681f3Smrg case ST_ATTACHMENT_FRONT_LEFT: 1347ec681f3Smrg /* already added */ 1357ec681f3Smrg if (!with_format) 1367ec681f3Smrg continue; 1377ec681f3Smrg att = __DRI_BUFFER_FRONT_LEFT; 1387ec681f3Smrg break; 1397ec681f3Smrg case ST_ATTACHMENT_BACK_LEFT: 1407ec681f3Smrg att = __DRI_BUFFER_BACK_LEFT; 1417ec681f3Smrg break; 1427ec681f3Smrg case ST_ATTACHMENT_FRONT_RIGHT: 1437ec681f3Smrg att = __DRI_BUFFER_FRONT_RIGHT; 1447ec681f3Smrg break; 1457ec681f3Smrg case ST_ATTACHMENT_BACK_RIGHT: 1467ec681f3Smrg att = __DRI_BUFFER_BACK_RIGHT; 1477ec681f3Smrg break; 1487ec681f3Smrg default: 1497ec681f3Smrg continue; 1507ec681f3Smrg } 1517ec681f3Smrg 1527ec681f3Smrg /* 1537ec681f3Smrg * In this switch statement we must support all formats that 1547ec681f3Smrg * may occur as the stvis->color_format. 1557ec681f3Smrg */ 1567ec681f3Smrg switch(format) { 1577ec681f3Smrg case PIPE_FORMAT_R16G16B16A16_FLOAT: 1587ec681f3Smrg depth = 64; 1597ec681f3Smrg break; 1607ec681f3Smrg case PIPE_FORMAT_R16G16B16X16_FLOAT: 1617ec681f3Smrg depth = 48; 1627ec681f3Smrg break; 1637ec681f3Smrg case PIPE_FORMAT_B10G10R10A2_UNORM: 1647ec681f3Smrg case PIPE_FORMAT_R10G10B10A2_UNORM: 1657ec681f3Smrg case PIPE_FORMAT_BGRA8888_UNORM: 1667ec681f3Smrg case PIPE_FORMAT_RGBA8888_UNORM: 1677ec681f3Smrg depth = 32; 1687ec681f3Smrg break; 1697ec681f3Smrg case PIPE_FORMAT_R10G10B10X2_UNORM: 1707ec681f3Smrg case PIPE_FORMAT_B10G10R10X2_UNORM: 1717ec681f3Smrg depth = 30; 1727ec681f3Smrg break; 1737ec681f3Smrg case PIPE_FORMAT_BGRX8888_UNORM: 1747ec681f3Smrg case PIPE_FORMAT_RGBX8888_UNORM: 1757ec681f3Smrg depth = 24; 1767ec681f3Smrg break; 1777ec681f3Smrg case PIPE_FORMAT_B5G6R5_UNORM: 1787ec681f3Smrg depth = 16; 1797ec681f3Smrg break; 1807ec681f3Smrg default: 1817ec681f3Smrg depth = util_format_get_blocksizebits(format); 1827ec681f3Smrg assert(!"Unexpected format in dri2_drawable_get_buffers()"); 1837ec681f3Smrg } 1847ec681f3Smrg 1857ec681f3Smrg attachments[num_attachments++] = att; 1867ec681f3Smrg if (with_format) { 1877ec681f3Smrg attachments[num_attachments++] = depth; 1887ec681f3Smrg } 1897ec681f3Smrg } 1907ec681f3Smrg 1917ec681f3Smrg if (with_format) { 1927ec681f3Smrg num_attachments /= 2; 1937ec681f3Smrg buffers = loader->getBuffersWithFormat(dri_drawable, 1947ec681f3Smrg &dri_drawable->w, &dri_drawable->h, 1957ec681f3Smrg attachments, num_attachments, 1967ec681f3Smrg &num_buffers, dri_drawable->loaderPrivate); 1977ec681f3Smrg } 1987ec681f3Smrg else { 1997ec681f3Smrg buffers = loader->getBuffers(dri_drawable, 2007ec681f3Smrg &dri_drawable->w, &dri_drawable->h, 2017ec681f3Smrg attachments, num_attachments, 2027ec681f3Smrg &num_buffers, dri_drawable->loaderPrivate); 2037ec681f3Smrg } 2047ec681f3Smrg 2057ec681f3Smrg if (buffers) 2067ec681f3Smrg *count = num_buffers; 2077ec681f3Smrg 2087ec681f3Smrg return buffers; 2097ec681f3Smrg} 2107ec681f3Smrg 2117ec681f3Smrgstatic bool 2127ec681f3Smrgdri_image_drawable_get_buffers(struct dri_drawable *drawable, 2137ec681f3Smrg struct __DRIimageList *images, 2147ec681f3Smrg const enum st_attachment_type *statts, 2157ec681f3Smrg unsigned statts_count) 2167ec681f3Smrg{ 2177ec681f3Smrg __DRIdrawable *dPriv = drawable->dPriv; 2187ec681f3Smrg __DRIscreen *sPriv = drawable->sPriv; 2197ec681f3Smrg unsigned int image_format = __DRI_IMAGE_FORMAT_NONE; 2207ec681f3Smrg enum pipe_format pf; 2217ec681f3Smrg uint32_t buffer_mask = 0; 2227ec681f3Smrg unsigned i, bind; 2237ec681f3Smrg 2247ec681f3Smrg for (i = 0; i < statts_count; i++) { 2257ec681f3Smrg dri_drawable_get_format(drawable, statts[i], &pf, &bind); 2267ec681f3Smrg if (pf == PIPE_FORMAT_NONE) 2277ec681f3Smrg continue; 2287ec681f3Smrg 2297ec681f3Smrg switch (statts[i]) { 2307ec681f3Smrg case ST_ATTACHMENT_FRONT_LEFT: 2317ec681f3Smrg buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; 2327ec681f3Smrg break; 2337ec681f3Smrg case ST_ATTACHMENT_BACK_LEFT: 2347ec681f3Smrg buffer_mask |= __DRI_IMAGE_BUFFER_BACK; 2357ec681f3Smrg break; 2367ec681f3Smrg default: 2377ec681f3Smrg continue; 2387ec681f3Smrg } 2397ec681f3Smrg 2407ec681f3Smrg switch (pf) { 2417ec681f3Smrg case PIPE_FORMAT_R16G16B16A16_FLOAT: 2427ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_ABGR16161616F; 2437ec681f3Smrg break; 2447ec681f3Smrg case PIPE_FORMAT_R16G16B16X16_FLOAT: 2457ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_XBGR16161616F; 2467ec681f3Smrg break; 2477ec681f3Smrg case PIPE_FORMAT_B5G5R5A1_UNORM: 2487ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_ARGB1555; 2497ec681f3Smrg break; 2507ec681f3Smrg case PIPE_FORMAT_B5G6R5_UNORM: 2517ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_RGB565; 2527ec681f3Smrg break; 2537ec681f3Smrg case PIPE_FORMAT_BGRX8888_UNORM: 2547ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_XRGB8888; 2557ec681f3Smrg break; 2567ec681f3Smrg case PIPE_FORMAT_BGRA8888_UNORM: 2577ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_ARGB8888; 2587ec681f3Smrg break; 2597ec681f3Smrg case PIPE_FORMAT_RGBX8888_UNORM: 2607ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_XBGR8888; 2617ec681f3Smrg break; 2627ec681f3Smrg case PIPE_FORMAT_RGBA8888_UNORM: 2637ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_ABGR8888; 2647ec681f3Smrg break; 2657ec681f3Smrg case PIPE_FORMAT_B10G10R10X2_UNORM: 2667ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_XRGB2101010; 2677ec681f3Smrg break; 2687ec681f3Smrg case PIPE_FORMAT_B10G10R10A2_UNORM: 2697ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_ARGB2101010; 2707ec681f3Smrg break; 2717ec681f3Smrg case PIPE_FORMAT_R10G10B10X2_UNORM: 2727ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_XBGR2101010; 2737ec681f3Smrg break; 2747ec681f3Smrg case PIPE_FORMAT_R10G10B10A2_UNORM: 2757ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_ABGR2101010; 2767ec681f3Smrg break; 2777ec681f3Smrg default: 2787ec681f3Smrg image_format = __DRI_IMAGE_FORMAT_NONE; 2797ec681f3Smrg break; 2807ec681f3Smrg } 2817ec681f3Smrg } 2827ec681f3Smrg 2837ec681f3Smrg return (*sPriv->image.loader->getBuffers) (dPriv, image_format, 2847ec681f3Smrg (uint32_t *) &drawable->base.stamp, 2857ec681f3Smrg dPriv->loaderPrivate, buffer_mask, 2867ec681f3Smrg images); 2877ec681f3Smrg} 2887ec681f3Smrg 2897ec681f3Smrgstatic __DRIbuffer * 2907ec681f3Smrgdri2_allocate_buffer(__DRIscreen *sPriv, 2917ec681f3Smrg unsigned attachment, unsigned format, 2927ec681f3Smrg int width, int height) 2937ec681f3Smrg{ 2947ec681f3Smrg struct dri_screen *screen = dri_screen(sPriv); 2957ec681f3Smrg struct dri2_buffer *buffer; 2967ec681f3Smrg struct pipe_resource templ; 2977ec681f3Smrg enum pipe_format pf; 2987ec681f3Smrg unsigned bind = 0; 2997ec681f3Smrg struct winsys_handle whandle; 3007ec681f3Smrg 3017ec681f3Smrg switch (attachment) { 3027ec681f3Smrg case __DRI_BUFFER_FRONT_LEFT: 3037ec681f3Smrg case __DRI_BUFFER_FAKE_FRONT_LEFT: 3047ec681f3Smrg bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 3057ec681f3Smrg break; 3067ec681f3Smrg case __DRI_BUFFER_BACK_LEFT: 3077ec681f3Smrg bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 3087ec681f3Smrg break; 3097ec681f3Smrg case __DRI_BUFFER_DEPTH: 3107ec681f3Smrg case __DRI_BUFFER_DEPTH_STENCIL: 3117ec681f3Smrg case __DRI_BUFFER_STENCIL: 3127ec681f3Smrg bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ 3137ec681f3Smrg break; 3147ec681f3Smrg } 3157ec681f3Smrg 3167ec681f3Smrg /* because we get the handle and stride */ 3177ec681f3Smrg bind |= PIPE_BIND_SHARED; 3187ec681f3Smrg 3197ec681f3Smrg switch (format) { 3207ec681f3Smrg case 64: 3217ec681f3Smrg pf = PIPE_FORMAT_R16G16B16A16_FLOAT; 3227ec681f3Smrg break; 3237ec681f3Smrg case 48: 3247ec681f3Smrg pf = PIPE_FORMAT_R16G16B16X16_FLOAT; 3257ec681f3Smrg break; 3267ec681f3Smrg case 32: 3277ec681f3Smrg pf = PIPE_FORMAT_BGRA8888_UNORM; 3287ec681f3Smrg break; 3297ec681f3Smrg case 30: 3307ec681f3Smrg pf = PIPE_FORMAT_B10G10R10X2_UNORM; 3317ec681f3Smrg break; 3327ec681f3Smrg case 24: 3337ec681f3Smrg pf = PIPE_FORMAT_BGRX8888_UNORM; 3347ec681f3Smrg break; 3357ec681f3Smrg case 16: 3367ec681f3Smrg pf = PIPE_FORMAT_Z16_UNORM; 3377ec681f3Smrg break; 3387ec681f3Smrg default: 3397ec681f3Smrg return NULL; 3407ec681f3Smrg } 3417ec681f3Smrg 3427ec681f3Smrg buffer = CALLOC_STRUCT(dri2_buffer); 3437ec681f3Smrg if (!buffer) 3447ec681f3Smrg return NULL; 3457ec681f3Smrg 3467ec681f3Smrg memset(&templ, 0, sizeof(templ)); 3477ec681f3Smrg templ.bind = bind; 3487ec681f3Smrg templ.format = pf; 3497ec681f3Smrg templ.target = PIPE_TEXTURE_2D; 3507ec681f3Smrg templ.last_level = 0; 3517ec681f3Smrg templ.width0 = width; 3527ec681f3Smrg templ.height0 = height; 3537ec681f3Smrg templ.depth0 = 1; 3547ec681f3Smrg templ.array_size = 1; 3557ec681f3Smrg 3567ec681f3Smrg buffer->resource = 3577ec681f3Smrg screen->base.screen->resource_create(screen->base.screen, &templ); 3587ec681f3Smrg if (!buffer->resource) { 3597ec681f3Smrg FREE(buffer); 3607ec681f3Smrg return NULL; 3617ec681f3Smrg } 3627ec681f3Smrg 3637ec681f3Smrg memset(&whandle, 0, sizeof(whandle)); 3647ec681f3Smrg if (screen->can_share_buffer) 3657ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_SHARED; 3667ec681f3Smrg else 3677ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_KMS; 3687ec681f3Smrg 3697ec681f3Smrg screen->base.screen->resource_get_handle(screen->base.screen, NULL, 3707ec681f3Smrg buffer->resource, &whandle, 3717ec681f3Smrg PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); 3727ec681f3Smrg 3737ec681f3Smrg buffer->base.attachment = attachment; 3747ec681f3Smrg buffer->base.name = whandle.handle; 3757ec681f3Smrg buffer->base.cpp = util_format_get_blocksize(pf); 3767ec681f3Smrg buffer->base.pitch = whandle.stride; 3777ec681f3Smrg 3787ec681f3Smrg return &buffer->base; 3797ec681f3Smrg} 3807ec681f3Smrg 3817ec681f3Smrgstatic void 3827ec681f3Smrgdri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) 3837ec681f3Smrg{ 3847ec681f3Smrg struct dri2_buffer *buffer = dri2_buffer(bPriv); 3857ec681f3Smrg 3867ec681f3Smrg pipe_resource_reference(&buffer->resource, NULL); 3877ec681f3Smrg FREE(buffer); 3887ec681f3Smrg} 3897ec681f3Smrg 3907ec681f3Smrg/* 3917ec681f3Smrg * Backend functions for st_framebuffer interface. 3927ec681f3Smrg */ 3937ec681f3Smrg 3947ec681f3Smrgstatic void 3957ec681f3Smrgdri2_allocate_textures(struct dri_context *ctx, 3967ec681f3Smrg struct dri_drawable *drawable, 3977ec681f3Smrg const enum st_attachment_type *statts, 3987ec681f3Smrg unsigned statts_count) 3997ec681f3Smrg{ 4007ec681f3Smrg __DRIscreen *sPriv = drawable->sPriv; 4017ec681f3Smrg __DRIdrawable *dri_drawable = drawable->dPriv; 4027ec681f3Smrg struct dri_screen *screen = dri_screen(sPriv); 4037ec681f3Smrg struct pipe_resource templ; 4047ec681f3Smrg boolean alloc_depthstencil = FALSE; 4057ec681f3Smrg unsigned i, j, bind; 4067ec681f3Smrg const __DRIimageLoaderExtension *image = sPriv->image.loader; 4077ec681f3Smrg /* Image specific variables */ 4087ec681f3Smrg struct __DRIimageList images; 4097ec681f3Smrg /* Dri2 specific variables */ 4107ec681f3Smrg __DRIbuffer *buffers = NULL; 4117ec681f3Smrg struct winsys_handle whandle; 4127ec681f3Smrg unsigned num_buffers = statts_count; 4137ec681f3Smrg 4147ec681f3Smrg assert(num_buffers <= __DRI_BUFFER_COUNT); 4157ec681f3Smrg 4167ec681f3Smrg /* First get the buffers from the loader */ 4177ec681f3Smrg if (image) { 4187ec681f3Smrg if (!dri_image_drawable_get_buffers(drawable, &images, 4197ec681f3Smrg statts, statts_count)) 4207ec681f3Smrg return; 4217ec681f3Smrg } 4227ec681f3Smrg else { 4237ec681f3Smrg buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); 4247ec681f3Smrg if (!buffers || (drawable->old_num == num_buffers && 4257ec681f3Smrg drawable->old_w == dri_drawable->w && 4267ec681f3Smrg drawable->old_h == dri_drawable->h && 4277ec681f3Smrg memcmp(drawable->old, buffers, 4287ec681f3Smrg sizeof(__DRIbuffer) * num_buffers) == 0)) 4297ec681f3Smrg return; 4307ec681f3Smrg } 4317ec681f3Smrg 4327ec681f3Smrg /* Second clean useless resources*/ 4337ec681f3Smrg 4347ec681f3Smrg /* See if we need a depth-stencil buffer. */ 4357ec681f3Smrg for (i = 0; i < statts_count; i++) { 4367ec681f3Smrg if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { 4377ec681f3Smrg alloc_depthstencil = TRUE; 4387ec681f3Smrg break; 4397ec681f3Smrg } 4407ec681f3Smrg } 4417ec681f3Smrg 4427ec681f3Smrg /* Delete the resources we won't need. */ 4437ec681f3Smrg for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 4447ec681f3Smrg /* Don't delete the depth-stencil buffer, we can reuse it. */ 4457ec681f3Smrg if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) 4467ec681f3Smrg continue; 4477ec681f3Smrg 4487ec681f3Smrg /* Flush the texture before unreferencing, so that other clients can 4497ec681f3Smrg * see what the driver has rendered. 4507ec681f3Smrg */ 4517ec681f3Smrg if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) { 4527ec681f3Smrg struct pipe_context *pipe = ctx->st->pipe; 4537ec681f3Smrg pipe->flush_resource(pipe, drawable->textures[i]); 4547ec681f3Smrg } 4557ec681f3Smrg 4567ec681f3Smrg pipe_resource_reference(&drawable->textures[i], NULL); 4577ec681f3Smrg } 4587ec681f3Smrg 4597ec681f3Smrg if (drawable->stvis.samples > 1) { 4607ec681f3Smrg for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 4617ec681f3Smrg boolean del = TRUE; 4627ec681f3Smrg 4637ec681f3Smrg /* Don't delete MSAA resources for the attachments which are enabled, 4647ec681f3Smrg * we can reuse them. */ 4657ec681f3Smrg for (j = 0; j < statts_count; j++) { 4667ec681f3Smrg if (i == statts[j]) { 4677ec681f3Smrg del = FALSE; 4687ec681f3Smrg break; 4697ec681f3Smrg } 4707ec681f3Smrg } 4717ec681f3Smrg 4727ec681f3Smrg if (del) { 4737ec681f3Smrg pipe_resource_reference(&drawable->msaa_textures[i], NULL); 4747ec681f3Smrg } 4757ec681f3Smrg } 4767ec681f3Smrg } 4777ec681f3Smrg 4787ec681f3Smrg /* Third use the buffers retrieved to fill the drawable info */ 4797ec681f3Smrg 4807ec681f3Smrg memset(&templ, 0, sizeof(templ)); 4817ec681f3Smrg templ.target = screen->target; 4827ec681f3Smrg templ.last_level = 0; 4837ec681f3Smrg templ.depth0 = 1; 4847ec681f3Smrg templ.array_size = 1; 4857ec681f3Smrg 4867ec681f3Smrg if (image) { 4877ec681f3Smrg if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { 4887ec681f3Smrg struct pipe_resource **buf = 4897ec681f3Smrg &drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; 4907ec681f3Smrg struct pipe_resource *texture = images.front->texture; 4917ec681f3Smrg 4927ec681f3Smrg dri_drawable->w = texture->width0; 4937ec681f3Smrg dri_drawable->h = texture->height0; 4947ec681f3Smrg 4957ec681f3Smrg pipe_resource_reference(buf, texture); 4967ec681f3Smrg } 4977ec681f3Smrg 4987ec681f3Smrg if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { 4997ec681f3Smrg struct pipe_resource **buf = 5007ec681f3Smrg &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; 5017ec681f3Smrg struct pipe_resource *texture = images.back->texture; 5027ec681f3Smrg 5037ec681f3Smrg dri_drawable->w = texture->width0; 5047ec681f3Smrg dri_drawable->h = texture->height0; 5057ec681f3Smrg 5067ec681f3Smrg pipe_resource_reference(buf, texture); 5077ec681f3Smrg } 5087ec681f3Smrg 5097ec681f3Smrg if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) { 5107ec681f3Smrg struct pipe_resource **buf = 5117ec681f3Smrg &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; 5127ec681f3Smrg struct pipe_resource *texture = images.back->texture; 5137ec681f3Smrg 5147ec681f3Smrg dri_drawable->w = texture->width0; 5157ec681f3Smrg dri_drawable->h = texture->height0; 5167ec681f3Smrg 5177ec681f3Smrg pipe_resource_reference(buf, texture); 5187ec681f3Smrg 5197ec681f3Smrg ctx->is_shared_buffer_bound = true; 5207ec681f3Smrg } else { 5217ec681f3Smrg ctx->is_shared_buffer_bound = false; 5227ec681f3Smrg } 5237ec681f3Smrg 5247ec681f3Smrg /* Note: if there is both a back and a front buffer, 5257ec681f3Smrg * then they have the same size. 5267ec681f3Smrg */ 5277ec681f3Smrg templ.width0 = dri_drawable->w; 5287ec681f3Smrg templ.height0 = dri_drawable->h; 5297ec681f3Smrg } 5307ec681f3Smrg else { 5317ec681f3Smrg memset(&whandle, 0, sizeof(whandle)); 5327ec681f3Smrg 5337ec681f3Smrg /* Process DRI-provided buffers and get pipe_resources. */ 5347ec681f3Smrg for (i = 0; i < num_buffers; i++) { 5357ec681f3Smrg __DRIbuffer *buf = &buffers[i]; 5367ec681f3Smrg enum st_attachment_type statt; 5377ec681f3Smrg enum pipe_format format; 5387ec681f3Smrg 5397ec681f3Smrg switch (buf->attachment) { 5407ec681f3Smrg case __DRI_BUFFER_FRONT_LEFT: 5417ec681f3Smrg if (!screen->auto_fake_front) { 5427ec681f3Smrg continue; /* invalid attachment */ 5437ec681f3Smrg } 5447ec681f3Smrg FALLTHROUGH; 5457ec681f3Smrg case __DRI_BUFFER_FAKE_FRONT_LEFT: 5467ec681f3Smrg statt = ST_ATTACHMENT_FRONT_LEFT; 5477ec681f3Smrg break; 5487ec681f3Smrg case __DRI_BUFFER_BACK_LEFT: 5497ec681f3Smrg statt = ST_ATTACHMENT_BACK_LEFT; 5507ec681f3Smrg break; 5517ec681f3Smrg default: 5527ec681f3Smrg continue; /* invalid attachment */ 5537ec681f3Smrg } 5547ec681f3Smrg 5557ec681f3Smrg dri_drawable_get_format(drawable, statt, &format, &bind); 5567ec681f3Smrg if (format == PIPE_FORMAT_NONE) 5577ec681f3Smrg continue; 5587ec681f3Smrg 5597ec681f3Smrg /* dri2_drawable_get_buffers has already filled dri_drawable->w 5607ec681f3Smrg * and dri_drawable->h */ 5617ec681f3Smrg templ.width0 = dri_drawable->w; 5627ec681f3Smrg templ.height0 = dri_drawable->h; 5637ec681f3Smrg templ.format = format; 5647ec681f3Smrg templ.bind = bind; 5657ec681f3Smrg whandle.handle = buf->name; 5667ec681f3Smrg whandle.stride = buf->pitch; 5677ec681f3Smrg whandle.offset = 0; 5687ec681f3Smrg whandle.format = format; 5697ec681f3Smrg whandle.modifier = DRM_FORMAT_MOD_INVALID; 5707ec681f3Smrg if (screen->can_share_buffer) 5717ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_SHARED; 5727ec681f3Smrg else 5737ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_KMS; 5747ec681f3Smrg drawable->textures[statt] = 5757ec681f3Smrg screen->base.screen->resource_from_handle(screen->base.screen, 5767ec681f3Smrg &templ, &whandle, 5777ec681f3Smrg PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); 5787ec681f3Smrg assert(drawable->textures[statt]); 5797ec681f3Smrg } 5807ec681f3Smrg } 5817ec681f3Smrg 5827ec681f3Smrg /* Allocate private MSAA colorbuffers. */ 5837ec681f3Smrg if (drawable->stvis.samples > 1) { 5847ec681f3Smrg for (i = 0; i < statts_count; i++) { 5857ec681f3Smrg enum st_attachment_type statt = statts[i]; 5867ec681f3Smrg 5877ec681f3Smrg if (statt == ST_ATTACHMENT_DEPTH_STENCIL) 5887ec681f3Smrg continue; 5897ec681f3Smrg 5907ec681f3Smrg if (drawable->textures[statt]) { 5917ec681f3Smrg templ.format = drawable->textures[statt]->format; 5927ec681f3Smrg templ.bind = drawable->textures[statt]->bind & 5937ec681f3Smrg ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED); 5947ec681f3Smrg templ.nr_samples = drawable->stvis.samples; 5957ec681f3Smrg templ.nr_storage_samples = drawable->stvis.samples; 5967ec681f3Smrg 5977ec681f3Smrg /* Try to reuse the resource. 5987ec681f3Smrg * (the other resource parameters should be constant) 5997ec681f3Smrg */ 6007ec681f3Smrg if (!drawable->msaa_textures[statt] || 6017ec681f3Smrg drawable->msaa_textures[statt]->width0 != templ.width0 || 6027ec681f3Smrg drawable->msaa_textures[statt]->height0 != templ.height0) { 6037ec681f3Smrg /* Allocate a new one. */ 6047ec681f3Smrg pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 6057ec681f3Smrg 6067ec681f3Smrg drawable->msaa_textures[statt] = 6077ec681f3Smrg screen->base.screen->resource_create(screen->base.screen, 6087ec681f3Smrg &templ); 6097ec681f3Smrg assert(drawable->msaa_textures[statt]); 6107ec681f3Smrg 6117ec681f3Smrg /* If there are any MSAA resources, we should initialize them 6127ec681f3Smrg * such that they contain the same data as the single-sample 6137ec681f3Smrg * resources we just got from the X server. 6147ec681f3Smrg * 6157ec681f3Smrg * The reason for this is that the gallium frontend (and 6167ec681f3Smrg * therefore the app) can access the MSAA resources only. 6177ec681f3Smrg * The single-sample resources are not exposed 6187ec681f3Smrg * to the gallium frontend. 6197ec681f3Smrg * 6207ec681f3Smrg */ 6217ec681f3Smrg dri_pipe_blit(ctx->st->pipe, 6227ec681f3Smrg drawable->msaa_textures[statt], 6237ec681f3Smrg drawable->textures[statt]); 6247ec681f3Smrg } 6257ec681f3Smrg } 6267ec681f3Smrg else { 6277ec681f3Smrg pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 6287ec681f3Smrg } 6297ec681f3Smrg } 6307ec681f3Smrg } 6317ec681f3Smrg 6327ec681f3Smrg /* Allocate a private depth-stencil buffer. */ 6337ec681f3Smrg if (alloc_depthstencil) { 6347ec681f3Smrg enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL; 6357ec681f3Smrg struct pipe_resource **zsbuf; 6367ec681f3Smrg enum pipe_format format; 6377ec681f3Smrg unsigned bind; 6387ec681f3Smrg 6397ec681f3Smrg dri_drawable_get_format(drawable, statt, &format, &bind); 6407ec681f3Smrg 6417ec681f3Smrg if (format) { 6427ec681f3Smrg templ.format = format; 6437ec681f3Smrg templ.bind = bind & ~PIPE_BIND_SHARED; 6447ec681f3Smrg 6457ec681f3Smrg if (drawable->stvis.samples > 1) { 6467ec681f3Smrg templ.nr_samples = drawable->stvis.samples; 6477ec681f3Smrg templ.nr_storage_samples = drawable->stvis.samples; 6487ec681f3Smrg zsbuf = &drawable->msaa_textures[statt]; 6497ec681f3Smrg } 6507ec681f3Smrg else { 6517ec681f3Smrg templ.nr_samples = 0; 6527ec681f3Smrg templ.nr_storage_samples = 0; 6537ec681f3Smrg zsbuf = &drawable->textures[statt]; 6547ec681f3Smrg } 6557ec681f3Smrg 6567ec681f3Smrg /* Try to reuse the resource. 6577ec681f3Smrg * (the other resource parameters should be constant) 6587ec681f3Smrg */ 6597ec681f3Smrg if (!*zsbuf || 6607ec681f3Smrg (*zsbuf)->width0 != templ.width0 || 6617ec681f3Smrg (*zsbuf)->height0 != templ.height0) { 6627ec681f3Smrg /* Allocate a new one. */ 6637ec681f3Smrg pipe_resource_reference(zsbuf, NULL); 6647ec681f3Smrg *zsbuf = screen->base.screen->resource_create(screen->base.screen, 6657ec681f3Smrg &templ); 6667ec681f3Smrg assert(*zsbuf); 6677ec681f3Smrg } 6687ec681f3Smrg } 6697ec681f3Smrg else { 6707ec681f3Smrg pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 6717ec681f3Smrg pipe_resource_reference(&drawable->textures[statt], NULL); 6727ec681f3Smrg } 6737ec681f3Smrg } 6747ec681f3Smrg 6757ec681f3Smrg /* For DRI2, we may get the same buffers again from the server. 6767ec681f3Smrg * To prevent useless imports of gem names, drawable->old* is used 6777ec681f3Smrg * to bypass the import if we get the same buffers. This doesn't apply 6787ec681f3Smrg * to DRI3/Wayland, users of image.loader, since the buffer is managed 6797ec681f3Smrg * by the client (no import), and the back buffer is going to change 6807ec681f3Smrg * at every redraw. 6817ec681f3Smrg */ 6827ec681f3Smrg if (!image) { 6837ec681f3Smrg drawable->old_num = num_buffers; 6847ec681f3Smrg drawable->old_w = dri_drawable->w; 6857ec681f3Smrg drawable->old_h = dri_drawable->h; 6867ec681f3Smrg memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers); 6877ec681f3Smrg } 6887ec681f3Smrg} 6897ec681f3Smrg 6907ec681f3Smrgstatic bool 6917ec681f3Smrgdri2_flush_frontbuffer(struct dri_context *ctx, 6927ec681f3Smrg struct dri_drawable *drawable, 6937ec681f3Smrg enum st_attachment_type statt) 6947ec681f3Smrg{ 6957ec681f3Smrg __DRIdrawable *dri_drawable = drawable->dPriv; 6967ec681f3Smrg const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; 6977ec681f3Smrg const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; 6987ec681f3Smrg const __DRImutableRenderBufferLoaderExtension *shared_buffer_loader = 6997ec681f3Smrg drawable->sPriv->mutableRenderBuffer.loader; 7007ec681f3Smrg struct pipe_context *pipe = ctx->st->pipe; 7017ec681f3Smrg struct pipe_fence_handle *fence = NULL; 7027ec681f3Smrg int fence_fd = -1; 7037ec681f3Smrg 7047ec681f3Smrg /* We need to flush for front buffer rendering when either we're using the 7057ec681f3Smrg * front buffer at the GL API level, or when EGL_KHR_mutable_render_buffer 7067ec681f3Smrg * has redirected GL_BACK to the front buffer. 7077ec681f3Smrg */ 7087ec681f3Smrg if (statt != ST_ATTACHMENT_FRONT_LEFT && 7097ec681f3Smrg (!ctx->is_shared_buffer_bound || statt != ST_ATTACHMENT_BACK_LEFT)) 7107ec681f3Smrg return false; 7117ec681f3Smrg 7127ec681f3Smrg if (drawable->stvis.samples > 1) { 7137ec681f3Smrg /* Resolve the buffer used for front rendering. */ 7147ec681f3Smrg dri_pipe_blit(ctx->st->pipe, drawable->textures[statt], 7157ec681f3Smrg drawable->msaa_textures[statt]); 7167ec681f3Smrg } 7177ec681f3Smrg 7187ec681f3Smrg if (drawable->textures[statt]) { 7197ec681f3Smrg pipe->flush_resource(pipe, drawable->textures[statt]); 7207ec681f3Smrg } 7217ec681f3Smrg 7227ec681f3Smrg if (ctx->is_shared_buffer_bound) { 7237ec681f3Smrg /* is_shared_buffer_bound should only be true with image extension: */ 7247ec681f3Smrg assert(image); 7257ec681f3Smrg pipe->flush(pipe, &fence, PIPE_FLUSH_FENCE_FD); 7267ec681f3Smrg } else { 7277ec681f3Smrg pipe->flush(pipe, NULL, 0); 7287ec681f3Smrg } 7297ec681f3Smrg 7307ec681f3Smrg if (image) { 7317ec681f3Smrg image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); 7327ec681f3Smrg if (ctx->is_shared_buffer_bound) { 7337ec681f3Smrg if (fence) 7347ec681f3Smrg fence_fd = pipe->screen->fence_get_fd(pipe->screen, fence); 7357ec681f3Smrg 7367ec681f3Smrg shared_buffer_loader->displaySharedBuffer(dri_drawable, fence_fd, 7377ec681f3Smrg dri_drawable->loaderPrivate); 7387ec681f3Smrg 7397ec681f3Smrg pipe->screen->fence_reference(pipe->screen, &fence, NULL); 7407ec681f3Smrg } 7417ec681f3Smrg } 7427ec681f3Smrg else if (loader->flushFrontBuffer) { 7437ec681f3Smrg loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); 7447ec681f3Smrg } 7457ec681f3Smrg 7467ec681f3Smrg return true; 7477ec681f3Smrg} 7487ec681f3Smrg 7497ec681f3Smrg/** 7507ec681f3Smrg * The struct dri_drawable flush_swapbuffers callback 7517ec681f3Smrg */ 7527ec681f3Smrgstatic void 7537ec681f3Smrgdri2_flush_swapbuffers(struct dri_context *ctx, 7547ec681f3Smrg struct dri_drawable *drawable) 7557ec681f3Smrg{ 7567ec681f3Smrg __DRIdrawable *dri_drawable = drawable->dPriv; 7577ec681f3Smrg const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; 7587ec681f3Smrg 7597ec681f3Smrg if (image && image->base.version >= 3 && image->flushSwapBuffers) { 7607ec681f3Smrg image->flushSwapBuffers(dri_drawable, dri_drawable->loaderPrivate); 7617ec681f3Smrg } 7627ec681f3Smrg} 7637ec681f3Smrg 7647ec681f3Smrgstatic void 7657ec681f3Smrgdri2_update_tex_buffer(struct dri_drawable *drawable, 7667ec681f3Smrg struct dri_context *ctx, 7677ec681f3Smrg struct pipe_resource *res) 7687ec681f3Smrg{ 7697ec681f3Smrg /* no-op */ 7707ec681f3Smrg} 7717ec681f3Smrg 7727ec681f3Smrgstatic const struct dri2_format_mapping r8_g8b8_mapping = { 7737ec681f3Smrg DRM_FORMAT_NV12, 7747ec681f3Smrg __DRI_IMAGE_FORMAT_NONE, 7757ec681f3Smrg __DRI_IMAGE_COMPONENTS_Y_UV, 7767ec681f3Smrg PIPE_FORMAT_R8_G8B8_420_UNORM, 7777ec681f3Smrg 2, 7787ec681f3Smrg { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 7797ec681f3Smrg { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } } 7807ec681f3Smrg}; 7817ec681f3Smrg 7827ec681f3Smrgstatic const struct dri2_format_mapping r8g8_r8b8_mapping = { 7837ec681f3Smrg DRM_FORMAT_YUYV, 7847ec681f3Smrg __DRI_IMAGE_FORMAT_NONE, 7857ec681f3Smrg __DRI_IMAGE_COMPONENTS_Y_XUXV, 7867ec681f3Smrg PIPE_FORMAT_R8G8_R8B8_UNORM, 2, 7877ec681f3Smrg { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 }, 7887ec681f3Smrg { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } 7897ec681f3Smrg}; 7907ec681f3Smrg 7917ec681f3Smrgstatic const struct dri2_format_mapping g8r8_b8r8_mapping = { 7927ec681f3Smrg DRM_FORMAT_UYVY, 7937ec681f3Smrg __DRI_IMAGE_FORMAT_NONE, 7947ec681f3Smrg __DRI_IMAGE_COMPONENTS_Y_XUXV, 7957ec681f3Smrg PIPE_FORMAT_G8R8_B8R8_UNORM, 2, 7967ec681f3Smrg { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 }, 7977ec681f3Smrg { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } 7987ec681f3Smrg}; 7997ec681f3Smrg 8007ec681f3Smrgstatic __DRIimage * 8017ec681f3Smrgdri2_create_image_from_winsys(__DRIscreen *_screen, 8027ec681f3Smrg int width, int height, const struct dri2_format_mapping *map, 8037ec681f3Smrg int num_handles, struct winsys_handle *whandle, 8047ec681f3Smrg bool is_protected_content, 8057ec681f3Smrg void *loaderPrivate) 8067ec681f3Smrg{ 8077ec681f3Smrg struct dri_screen *screen = dri_screen(_screen); 8087ec681f3Smrg struct pipe_screen *pscreen = screen->base.screen; 8097ec681f3Smrg __DRIimage *img; 8107ec681f3Smrg struct pipe_resource templ; 8117ec681f3Smrg unsigned tex_usage = 0; 8127ec681f3Smrg int i; 8137ec681f3Smrg bool use_lowered = false; 8147ec681f3Smrg const unsigned format_planes = util_format_get_num_planes(map->pipe_format); 8157ec681f3Smrg 8167ec681f3Smrg if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0, 8177ec681f3Smrg PIPE_BIND_RENDER_TARGET)) 8187ec681f3Smrg tex_usage |= PIPE_BIND_RENDER_TARGET; 8197ec681f3Smrg if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0, 8207ec681f3Smrg PIPE_BIND_SAMPLER_VIEW)) 8217ec681f3Smrg tex_usage |= PIPE_BIND_SAMPLER_VIEW; 8227ec681f3Smrg 8237ec681f3Smrg /* For NV12, see if we have support for sampling r8_b8g8 */ 8247ec681f3Smrg if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV12 && 8257ec681f3Smrg pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8B8_420_UNORM, 8267ec681f3Smrg screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { 8277ec681f3Smrg map = &r8_g8b8_mapping; 8287ec681f3Smrg tex_usage |= PIPE_BIND_SAMPLER_VIEW; 8297ec681f3Smrg } 8307ec681f3Smrg 8317ec681f3Smrg /* If the hardware supports R8G8_R8B8 style subsampled RGB formats, these 8327ec681f3Smrg * can be used for YUYV and UYVY formats. 8337ec681f3Smrg */ 8347ec681f3Smrg if (!tex_usage && map->pipe_format == PIPE_FORMAT_YUYV && 8357ec681f3Smrg pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8G8_R8B8_UNORM, 8367ec681f3Smrg screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { 8377ec681f3Smrg map = &r8g8_r8b8_mapping; 8387ec681f3Smrg tex_usage |= PIPE_BIND_SAMPLER_VIEW; 8397ec681f3Smrg } 8407ec681f3Smrg 8417ec681f3Smrg if (!tex_usage && map->pipe_format == PIPE_FORMAT_UYVY && 8427ec681f3Smrg pscreen->is_format_supported(pscreen, PIPE_FORMAT_G8R8_B8R8_UNORM, 8437ec681f3Smrg screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { 8447ec681f3Smrg map = &g8r8_b8r8_mapping; 8457ec681f3Smrg tex_usage |= PIPE_BIND_SAMPLER_VIEW; 8467ec681f3Smrg } 8477ec681f3Smrg 8487ec681f3Smrg if (!tex_usage && util_format_is_yuv(map->pipe_format)) { 8497ec681f3Smrg /* YUV format sampling can be emulated by the GL gallium frontend by 8507ec681f3Smrg * using multiple samplers of varying formats. 8517ec681f3Smrg * If no tex_usage is set and we detect a YUV format, 8527ec681f3Smrg * test for support of all planes' sampler formats and 8537ec681f3Smrg * add sampler view usage. 8547ec681f3Smrg */ 8557ec681f3Smrg use_lowered = true; 8567ec681f3Smrg if (dri2_yuv_dma_buf_supported(screen, map)) 8577ec681f3Smrg tex_usage |= PIPE_BIND_SAMPLER_VIEW; 8587ec681f3Smrg } 8597ec681f3Smrg 8607ec681f3Smrg if (!tex_usage) 8617ec681f3Smrg return NULL; 8627ec681f3Smrg 8637ec681f3Smrg if (is_protected_content) 8647ec681f3Smrg tex_usage |= PIPE_BIND_PROTECTED; 8657ec681f3Smrg 8667ec681f3Smrg img = CALLOC_STRUCT(__DRIimageRec); 8677ec681f3Smrg if (!img) 8687ec681f3Smrg return NULL; 8697ec681f3Smrg 8707ec681f3Smrg memset(&templ, 0, sizeof(templ)); 8717ec681f3Smrg templ.bind = tex_usage; 8727ec681f3Smrg templ.target = screen->target; 8737ec681f3Smrg templ.last_level = 0; 8747ec681f3Smrg templ.depth0 = 1; 8757ec681f3Smrg templ.array_size = 1; 8767ec681f3Smrg 8777ec681f3Smrg for (i = num_handles - 1; i >= format_planes; i--) { 8787ec681f3Smrg struct pipe_resource *tex; 8797ec681f3Smrg 8807ec681f3Smrg templ.next = img->texture; 8817ec681f3Smrg 8827ec681f3Smrg tex = pscreen->resource_from_handle(pscreen, &templ, &whandle[i], 8837ec681f3Smrg PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 8847ec681f3Smrg if (!tex) { 8857ec681f3Smrg pipe_resource_reference(&img->texture, NULL); 8867ec681f3Smrg FREE(img); 8877ec681f3Smrg return NULL; 8887ec681f3Smrg } 8897ec681f3Smrg 8907ec681f3Smrg img->texture = tex; 8917ec681f3Smrg } 8927ec681f3Smrg 8937ec681f3Smrg for (i = (use_lowered ? map->nplanes : format_planes) - 1; i >= 0; i--) { 8947ec681f3Smrg struct pipe_resource *tex; 8957ec681f3Smrg 8967ec681f3Smrg templ.next = img->texture; 8977ec681f3Smrg templ.width0 = width >> map->planes[i].width_shift; 8987ec681f3Smrg templ.height0 = height >> map->planes[i].height_shift; 8997ec681f3Smrg if (use_lowered) 9007ec681f3Smrg templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format); 9017ec681f3Smrg else 9027ec681f3Smrg templ.format = map->pipe_format; 9037ec681f3Smrg assert(templ.format != PIPE_FORMAT_NONE); 9047ec681f3Smrg 9057ec681f3Smrg tex = pscreen->resource_from_handle(pscreen, 9067ec681f3Smrg &templ, &whandle[use_lowered ? map->planes[i].buffer_index : i], 9077ec681f3Smrg PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 9087ec681f3Smrg if (!tex) { 9097ec681f3Smrg pipe_resource_reference(&img->texture, NULL); 9107ec681f3Smrg FREE(img); 9117ec681f3Smrg return NULL; 9127ec681f3Smrg } 9137ec681f3Smrg 9147ec681f3Smrg /* Reject image creation if there's an inconsistency between 9157ec681f3Smrg * content protection status of tex and img. 9167ec681f3Smrg */ 9177ec681f3Smrg const struct driOptionCache *optionCache = &screen->dev->option_cache; 9187ec681f3Smrg if (!driQueryOptionb(optionCache, "disable_protected_content_check") && 9197ec681f3Smrg (bool)(tex->bind & PIPE_BIND_PROTECTED) != is_protected_content) { 9207ec681f3Smrg pipe_resource_reference(&img->texture, NULL); 9217ec681f3Smrg pipe_resource_reference(&tex, NULL); 9227ec681f3Smrg FREE(img); 9237ec681f3Smrg return NULL; 9247ec681f3Smrg } 9257ec681f3Smrg 9267ec681f3Smrg img->texture = tex; 9277ec681f3Smrg } 9287ec681f3Smrg 9297ec681f3Smrg img->level = 0; 9307ec681f3Smrg img->layer = 0; 9317ec681f3Smrg img->use = 0; 9327ec681f3Smrg img->loader_private = loaderPrivate; 9337ec681f3Smrg img->sPriv = _screen; 9347ec681f3Smrg 9357ec681f3Smrg return img; 9367ec681f3Smrg} 9377ec681f3Smrg 9387ec681f3Smrgstatic __DRIimage * 9397ec681f3Smrgdri2_create_image_from_name(__DRIscreen *_screen, 9407ec681f3Smrg int width, int height, int format, 9417ec681f3Smrg int name, int pitch, void *loaderPrivate) 9427ec681f3Smrg{ 9437ec681f3Smrg const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); 9447ec681f3Smrg struct winsys_handle whandle; 9457ec681f3Smrg __DRIimage *img; 9467ec681f3Smrg 9477ec681f3Smrg if (!map) 9487ec681f3Smrg return NULL; 9497ec681f3Smrg 9507ec681f3Smrg memset(&whandle, 0, sizeof(whandle)); 9517ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_SHARED; 9527ec681f3Smrg whandle.handle = name; 9537ec681f3Smrg whandle.format = map->pipe_format; 9547ec681f3Smrg whandle.modifier = DRM_FORMAT_MOD_INVALID; 9557ec681f3Smrg 9567ec681f3Smrg whandle.stride = pitch * util_format_get_blocksize(map->pipe_format); 9577ec681f3Smrg 9587ec681f3Smrg img = dri2_create_image_from_winsys(_screen, width, height, map, 9597ec681f3Smrg 1, &whandle, false, loaderPrivate); 9607ec681f3Smrg 9617ec681f3Smrg if (!img) 9627ec681f3Smrg return NULL; 9637ec681f3Smrg 9647ec681f3Smrg img->dri_components = map->dri_components; 9657ec681f3Smrg img->dri_fourcc = map->dri_fourcc; 9667ec681f3Smrg img->dri_format = map->dri_format; 9677ec681f3Smrg 9687ec681f3Smrg return img; 9697ec681f3Smrg} 9707ec681f3Smrg 9717ec681f3Smrgstatic unsigned 9727ec681f3Smrgdri2_get_modifier_num_planes(__DRIscreen *_screen, 9737ec681f3Smrg uint64_t modifier, int fourcc) 9747ec681f3Smrg{ 9757ec681f3Smrg struct pipe_screen *pscreen = dri_screen(_screen)->base.screen; 9767ec681f3Smrg const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); 9777ec681f3Smrg 9787ec681f3Smrg if (!map) 9797ec681f3Smrg return 0; 9807ec681f3Smrg 9817ec681f3Smrg switch (modifier) { 9827ec681f3Smrg case DRM_FORMAT_MOD_LINEAR: 9837ec681f3Smrg /* DRM_FORMAT_MOD_NONE is the same as LINEAR */ 9847ec681f3Smrg case DRM_FORMAT_MOD_INVALID: 9857ec681f3Smrg return util_format_get_num_planes(map->pipe_format); 9867ec681f3Smrg default: 9877ec681f3Smrg if (!pscreen->is_dmabuf_modifier_supported || 9887ec681f3Smrg !pscreen->is_dmabuf_modifier_supported(pscreen, modifier, 9897ec681f3Smrg map->pipe_format, NULL)) { 9907ec681f3Smrg return 0; 9917ec681f3Smrg } 9927ec681f3Smrg 9937ec681f3Smrg if (pscreen->get_dmabuf_modifier_planes) { 9947ec681f3Smrg return pscreen->get_dmabuf_modifier_planes(pscreen, modifier, 9957ec681f3Smrg map->pipe_format); 9967ec681f3Smrg } 9977ec681f3Smrg 9987ec681f3Smrg return map->nplanes; 9997ec681f3Smrg } 10007ec681f3Smrg} 10017ec681f3Smrg 10027ec681f3Smrgstatic __DRIimage * 10037ec681f3Smrgdri2_create_image_from_fd(__DRIscreen *_screen, 10047ec681f3Smrg int width, int height, int fourcc, 10057ec681f3Smrg uint64_t modifier, int *fds, int num_fds, 10067ec681f3Smrg int *strides, int *offsets, bool protected_content, 10077ec681f3Smrg unsigned *error, void *loaderPrivate) 10087ec681f3Smrg{ 10097ec681f3Smrg struct winsys_handle whandles[4]; 10107ec681f3Smrg const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); 10117ec681f3Smrg __DRIimage *img = NULL; 10127ec681f3Smrg unsigned err = __DRI_IMAGE_ERROR_SUCCESS; 10137ec681f3Smrg int i; 10147ec681f3Smrg const int expected_num_fds = dri2_get_modifier_num_planes(_screen, modifier, fourcc); 10157ec681f3Smrg 10167ec681f3Smrg if (!map || expected_num_fds == 0) { 10177ec681f3Smrg err = __DRI_IMAGE_ERROR_BAD_MATCH; 10187ec681f3Smrg goto exit; 10197ec681f3Smrg } 10207ec681f3Smrg 10217ec681f3Smrg if (num_fds != expected_num_fds) { 10227ec681f3Smrg err = __DRI_IMAGE_ERROR_BAD_MATCH; 10237ec681f3Smrg goto exit; 10247ec681f3Smrg } 10257ec681f3Smrg 10267ec681f3Smrg memset(whandles, 0, sizeof(whandles)); 10277ec681f3Smrg 10287ec681f3Smrg for (i = 0; i < num_fds; i++) { 10297ec681f3Smrg if (fds[i] < 0) { 10307ec681f3Smrg err = __DRI_IMAGE_ERROR_BAD_ALLOC; 10317ec681f3Smrg goto exit; 10327ec681f3Smrg } 10337ec681f3Smrg 10347ec681f3Smrg whandles[i].type = WINSYS_HANDLE_TYPE_FD; 10357ec681f3Smrg whandles[i].handle = (unsigned)fds[i]; 10367ec681f3Smrg whandles[i].stride = (unsigned)strides[i]; 10377ec681f3Smrg whandles[i].offset = (unsigned)offsets[i]; 10387ec681f3Smrg whandles[i].format = map->pipe_format; 10397ec681f3Smrg whandles[i].modifier = modifier; 10407ec681f3Smrg whandles[i].plane = i; 10417ec681f3Smrg } 10427ec681f3Smrg 10437ec681f3Smrg img = dri2_create_image_from_winsys(_screen, width, height, map, 10447ec681f3Smrg num_fds, whandles, protected_content, 10457ec681f3Smrg loaderPrivate); 10467ec681f3Smrg if(img == NULL) { 10477ec681f3Smrg err = __DRI_IMAGE_ERROR_BAD_ALLOC; 10487ec681f3Smrg goto exit; 10497ec681f3Smrg } 10507ec681f3Smrg 10517ec681f3Smrg img->dri_components = map->dri_components; 10527ec681f3Smrg img->dri_fourcc = fourcc; 10537ec681f3Smrg img->dri_format = map->dri_format; 10547ec681f3Smrg img->imported_dmabuf = TRUE; 10557ec681f3Smrg 10567ec681f3Smrgexit: 10577ec681f3Smrg if (error) 10587ec681f3Smrg *error = err; 10597ec681f3Smrg 10607ec681f3Smrg return img; 10617ec681f3Smrg} 10627ec681f3Smrg 10637ec681f3Smrgstatic __DRIimage * 10647ec681f3Smrgdri2_create_image_common(__DRIscreen *_screen, 10657ec681f3Smrg int width, int height, 10667ec681f3Smrg int format, unsigned int use, 10677ec681f3Smrg const uint64_t *modifiers, 10687ec681f3Smrg const unsigned count, 10697ec681f3Smrg void *loaderPrivate) 10707ec681f3Smrg{ 10717ec681f3Smrg const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); 10727ec681f3Smrg struct dri_screen *screen = dri_screen(_screen); 10737ec681f3Smrg struct pipe_screen *pscreen = screen->base.screen; 10747ec681f3Smrg __DRIimage *img; 10757ec681f3Smrg struct pipe_resource templ; 10767ec681f3Smrg unsigned tex_usage = 0; 10777ec681f3Smrg 10787ec681f3Smrg if (!map) 10797ec681f3Smrg return NULL; 10807ec681f3Smrg 10817ec681f3Smrg if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 10827ec681f3Smrg 0, 0, PIPE_BIND_RENDER_TARGET)) 10837ec681f3Smrg tex_usage |= PIPE_BIND_RENDER_TARGET; 10847ec681f3Smrg if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 10857ec681f3Smrg 0, 0, PIPE_BIND_SAMPLER_VIEW)) 10867ec681f3Smrg tex_usage |= PIPE_BIND_SAMPLER_VIEW; 10877ec681f3Smrg 10887ec681f3Smrg if (!tex_usage) 10897ec681f3Smrg return NULL; 10907ec681f3Smrg 10917ec681f3Smrg if (use & __DRI_IMAGE_USE_SCANOUT) 10927ec681f3Smrg tex_usage |= PIPE_BIND_SCANOUT; 10937ec681f3Smrg if (use & __DRI_IMAGE_USE_SHARE) 10947ec681f3Smrg tex_usage |= PIPE_BIND_SHARED; 10957ec681f3Smrg if (use & __DRI_IMAGE_USE_LINEAR) 10967ec681f3Smrg tex_usage |= PIPE_BIND_LINEAR; 10977ec681f3Smrg if (use & __DRI_IMAGE_USE_CURSOR) { 10987ec681f3Smrg if (width != 64 || height != 64) 10997ec681f3Smrg return NULL; 11007ec681f3Smrg tex_usage |= PIPE_BIND_CURSOR; 11017ec681f3Smrg } 11027ec681f3Smrg if (use & __DRI_IMAGE_USE_PROTECTED) 11037ec681f3Smrg tex_usage |= PIPE_BIND_PROTECTED; 11047ec681f3Smrg 11057ec681f3Smrg img = CALLOC_STRUCT(__DRIimageRec); 11067ec681f3Smrg if (!img) 11077ec681f3Smrg return NULL; 11087ec681f3Smrg 11097ec681f3Smrg memset(&templ, 0, sizeof(templ)); 11107ec681f3Smrg templ.bind = tex_usage; 11117ec681f3Smrg templ.format = map->pipe_format; 11127ec681f3Smrg templ.target = PIPE_TEXTURE_2D; 11137ec681f3Smrg templ.last_level = 0; 11147ec681f3Smrg templ.width0 = width; 11157ec681f3Smrg templ.height0 = height; 11167ec681f3Smrg templ.depth0 = 1; 11177ec681f3Smrg templ.array_size = 1; 11187ec681f3Smrg 11197ec681f3Smrg if (modifiers) 11207ec681f3Smrg img->texture = 11217ec681f3Smrg screen->base.screen 11227ec681f3Smrg ->resource_create_with_modifiers(screen->base.screen, 11237ec681f3Smrg &templ, 11247ec681f3Smrg modifiers, 11257ec681f3Smrg count); 11267ec681f3Smrg else 11277ec681f3Smrg img->texture = 11287ec681f3Smrg screen->base.screen->resource_create(screen->base.screen, &templ); 11297ec681f3Smrg if (!img->texture) { 11307ec681f3Smrg FREE(img); 11317ec681f3Smrg return NULL; 11327ec681f3Smrg } 11337ec681f3Smrg 11347ec681f3Smrg img->level = 0; 11357ec681f3Smrg img->layer = 0; 11367ec681f3Smrg img->dri_format = format; 11377ec681f3Smrg img->dri_fourcc = map->dri_fourcc; 11387ec681f3Smrg img->dri_components = 0; 11397ec681f3Smrg img->use = use; 11407ec681f3Smrg 11417ec681f3Smrg img->loader_private = loaderPrivate; 11427ec681f3Smrg img->sPriv = _screen; 11437ec681f3Smrg return img; 11447ec681f3Smrg} 11457ec681f3Smrg 11467ec681f3Smrgstatic __DRIimage * 11477ec681f3Smrgdri2_create_image(__DRIscreen *_screen, 11487ec681f3Smrg int width, int height, int format, 11497ec681f3Smrg unsigned int use, void *loaderPrivate) 11507ec681f3Smrg{ 11517ec681f3Smrg return dri2_create_image_common(_screen, width, height, format, use, 11527ec681f3Smrg NULL /* modifiers */, 0 /* count */, 11537ec681f3Smrg loaderPrivate); 11547ec681f3Smrg} 11557ec681f3Smrg 11567ec681f3Smrgstatic __DRIimage * 11577ec681f3Smrgdri2_create_image_with_modifiers(__DRIscreen *dri_screen, 11587ec681f3Smrg int width, int height, int format, 11597ec681f3Smrg const uint64_t *modifiers, 11607ec681f3Smrg const unsigned count, 11617ec681f3Smrg void *loaderPrivate) 11627ec681f3Smrg{ 11637ec681f3Smrg return dri2_create_image_common(dri_screen, width, height, format, 11647ec681f3Smrg __DRI_IMAGE_USE_SHARE, modifiers, count, 11657ec681f3Smrg loaderPrivate); 11667ec681f3Smrg} 11677ec681f3Smrg 11687ec681f3Smrgstatic __DRIimage * 11697ec681f3Smrgdri2_create_image_with_modifiers2(__DRIscreen *dri_screen, 11707ec681f3Smrg int width, int height, int format, 11717ec681f3Smrg const uint64_t *modifiers, 11727ec681f3Smrg const unsigned count, unsigned int use, 11737ec681f3Smrg void *loaderPrivate) 11747ec681f3Smrg{ 11757ec681f3Smrg return dri2_create_image_common(dri_screen, width, height, format, use, 11767ec681f3Smrg modifiers, count, loaderPrivate); 11777ec681f3Smrg} 11787ec681f3Smrg 11797ec681f3Smrgstatic bool 11807ec681f3Smrgdri2_query_image_common(__DRIimage *image, int attrib, int *value) 11817ec681f3Smrg{ 11827ec681f3Smrg switch (attrib) { 11837ec681f3Smrg case __DRI_IMAGE_ATTRIB_FORMAT: 11847ec681f3Smrg *value = image->dri_format; 11857ec681f3Smrg return true; 11867ec681f3Smrg case __DRI_IMAGE_ATTRIB_WIDTH: 11877ec681f3Smrg *value = image->texture->width0; 11887ec681f3Smrg return true; 11897ec681f3Smrg case __DRI_IMAGE_ATTRIB_HEIGHT: 11907ec681f3Smrg *value = image->texture->height0; 11917ec681f3Smrg return true; 11927ec681f3Smrg case __DRI_IMAGE_ATTRIB_COMPONENTS: 11937ec681f3Smrg if (image->dri_components == 0) 11947ec681f3Smrg return false; 11957ec681f3Smrg *value = image->dri_components; 11967ec681f3Smrg return true; 11977ec681f3Smrg case __DRI_IMAGE_ATTRIB_FOURCC: 11987ec681f3Smrg if (image->dri_fourcc) { 11997ec681f3Smrg *value = image->dri_fourcc; 12007ec681f3Smrg } else { 12017ec681f3Smrg const struct dri2_format_mapping *map; 12027ec681f3Smrg 12037ec681f3Smrg map = dri2_get_mapping_by_format(image->dri_format); 12047ec681f3Smrg if (!map) 12057ec681f3Smrg return false; 12067ec681f3Smrg 12077ec681f3Smrg *value = map->dri_fourcc; 12087ec681f3Smrg } 12097ec681f3Smrg return true; 12107ec681f3Smrg default: 12117ec681f3Smrg return false; 12127ec681f3Smrg } 12137ec681f3Smrg} 12147ec681f3Smrg 12157ec681f3Smrgstatic bool 12167ec681f3Smrgdri2_query_image_by_resource_handle(__DRIimage *image, int attrib, int *value) 12177ec681f3Smrg{ 12187ec681f3Smrg struct pipe_screen *pscreen = image->texture->screen; 12197ec681f3Smrg struct winsys_handle whandle; 12207ec681f3Smrg struct pipe_resource *tex; 12217ec681f3Smrg unsigned usage; 12227ec681f3Smrg memset(&whandle, 0, sizeof(whandle)); 12237ec681f3Smrg whandle.plane = image->plane; 12247ec681f3Smrg int i; 12257ec681f3Smrg 12267ec681f3Smrg switch (attrib) { 12277ec681f3Smrg case __DRI_IMAGE_ATTRIB_STRIDE: 12287ec681f3Smrg case __DRI_IMAGE_ATTRIB_OFFSET: 12297ec681f3Smrg case __DRI_IMAGE_ATTRIB_HANDLE: 12307ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_KMS; 12317ec681f3Smrg break; 12327ec681f3Smrg case __DRI_IMAGE_ATTRIB_NAME: 12337ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_SHARED; 12347ec681f3Smrg break; 12357ec681f3Smrg case __DRI_IMAGE_ATTRIB_FD: 12367ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_FD; 12377ec681f3Smrg break; 12387ec681f3Smrg case __DRI_IMAGE_ATTRIB_NUM_PLANES: 12397ec681f3Smrg for (i = 0, tex = image->texture; tex; tex = tex->next) 12407ec681f3Smrg i++; 12417ec681f3Smrg *value = i; 12427ec681f3Smrg return true; 12437ec681f3Smrg case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: 12447ec681f3Smrg case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: 12457ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_KMS; 12467ec681f3Smrg whandle.modifier = DRM_FORMAT_MOD_INVALID; 12477ec681f3Smrg break; 12487ec681f3Smrg default: 12497ec681f3Smrg return false; 12507ec681f3Smrg } 12517ec681f3Smrg 12527ec681f3Smrg usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; 12537ec681f3Smrg 12547ec681f3Smrg if (image->use & __DRI_IMAGE_USE_BACKBUFFER) 12557ec681f3Smrg usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH; 12567ec681f3Smrg 12577ec681f3Smrg if (!pscreen->resource_get_handle(pscreen, NULL, image->texture, 12587ec681f3Smrg &whandle, usage)) 12597ec681f3Smrg return false; 12607ec681f3Smrg 12617ec681f3Smrg switch (attrib) { 12627ec681f3Smrg case __DRI_IMAGE_ATTRIB_STRIDE: 12637ec681f3Smrg *value = whandle.stride; 12647ec681f3Smrg return true; 12657ec681f3Smrg case __DRI_IMAGE_ATTRIB_OFFSET: 12667ec681f3Smrg *value = whandle.offset; 12677ec681f3Smrg return true; 12687ec681f3Smrg case __DRI_IMAGE_ATTRIB_HANDLE: 12697ec681f3Smrg case __DRI_IMAGE_ATTRIB_NAME: 12707ec681f3Smrg case __DRI_IMAGE_ATTRIB_FD: 12717ec681f3Smrg *value = whandle.handle; 12727ec681f3Smrg return true; 12737ec681f3Smrg case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: 12747ec681f3Smrg if (whandle.modifier == DRM_FORMAT_MOD_INVALID) 12757ec681f3Smrg return false; 12767ec681f3Smrg *value = (whandle.modifier >> 32) & 0xffffffff; 12777ec681f3Smrg return true; 12787ec681f3Smrg case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: 12797ec681f3Smrg if (whandle.modifier == DRM_FORMAT_MOD_INVALID) 12807ec681f3Smrg return false; 12817ec681f3Smrg *value = whandle.modifier & 0xffffffff; 12827ec681f3Smrg return true; 12837ec681f3Smrg default: 12847ec681f3Smrg return false; 12857ec681f3Smrg } 12867ec681f3Smrg} 12877ec681f3Smrg 12887ec681f3Smrgstatic bool 12897ec681f3Smrgdri2_resource_get_param(__DRIimage *image, enum pipe_resource_param param, 12907ec681f3Smrg unsigned handle_usage, uint64_t *value) 12917ec681f3Smrg{ 12927ec681f3Smrg struct pipe_screen *pscreen = image->texture->screen; 12937ec681f3Smrg if (!pscreen->resource_get_param) 12947ec681f3Smrg return false; 12957ec681f3Smrg 12967ec681f3Smrg if (image->use & __DRI_IMAGE_USE_BACKBUFFER) 12977ec681f3Smrg handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH; 12987ec681f3Smrg 12997ec681f3Smrg return pscreen->resource_get_param(pscreen, NULL, image->texture, 13007ec681f3Smrg image->plane, 0, 0, param, handle_usage, 13017ec681f3Smrg value); 13027ec681f3Smrg} 13037ec681f3Smrg 13047ec681f3Smrgstatic bool 13057ec681f3Smrgdri2_query_image_by_resource_param(__DRIimage *image, int attrib, int *value) 13067ec681f3Smrg{ 13077ec681f3Smrg enum pipe_resource_param param; 13087ec681f3Smrg uint64_t res_param; 13097ec681f3Smrg unsigned handle_usage; 13107ec681f3Smrg 13117ec681f3Smrg if (!image->texture->screen->resource_get_param) 13127ec681f3Smrg return false; 13137ec681f3Smrg 13147ec681f3Smrg switch (attrib) { 13157ec681f3Smrg case __DRI_IMAGE_ATTRIB_STRIDE: 13167ec681f3Smrg param = PIPE_RESOURCE_PARAM_STRIDE; 13177ec681f3Smrg break; 13187ec681f3Smrg case __DRI_IMAGE_ATTRIB_OFFSET: 13197ec681f3Smrg param = PIPE_RESOURCE_PARAM_OFFSET; 13207ec681f3Smrg break; 13217ec681f3Smrg case __DRI_IMAGE_ATTRIB_NUM_PLANES: 13227ec681f3Smrg param = PIPE_RESOURCE_PARAM_NPLANES; 13237ec681f3Smrg break; 13247ec681f3Smrg case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: 13257ec681f3Smrg case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: 13267ec681f3Smrg param = PIPE_RESOURCE_PARAM_MODIFIER; 13277ec681f3Smrg break; 13287ec681f3Smrg case __DRI_IMAGE_ATTRIB_HANDLE: 13297ec681f3Smrg param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS; 13307ec681f3Smrg break; 13317ec681f3Smrg case __DRI_IMAGE_ATTRIB_NAME: 13327ec681f3Smrg param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED; 13337ec681f3Smrg break; 13347ec681f3Smrg case __DRI_IMAGE_ATTRIB_FD: 13357ec681f3Smrg param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD; 13367ec681f3Smrg break; 13377ec681f3Smrg default: 13387ec681f3Smrg return false; 13397ec681f3Smrg } 13407ec681f3Smrg 13417ec681f3Smrg handle_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; 13427ec681f3Smrg 13437ec681f3Smrg if (!dri2_resource_get_param(image, param, handle_usage, &res_param)) 13447ec681f3Smrg return false; 13457ec681f3Smrg 13467ec681f3Smrg switch (attrib) { 13477ec681f3Smrg case __DRI_IMAGE_ATTRIB_STRIDE: 13487ec681f3Smrg case __DRI_IMAGE_ATTRIB_OFFSET: 13497ec681f3Smrg case __DRI_IMAGE_ATTRIB_NUM_PLANES: 13507ec681f3Smrg if (res_param > INT_MAX) 13517ec681f3Smrg return false; 13527ec681f3Smrg *value = (int)res_param; 13537ec681f3Smrg return true; 13547ec681f3Smrg case __DRI_IMAGE_ATTRIB_HANDLE: 13557ec681f3Smrg case __DRI_IMAGE_ATTRIB_NAME: 13567ec681f3Smrg case __DRI_IMAGE_ATTRIB_FD: 13577ec681f3Smrg if (res_param > UINT_MAX) 13587ec681f3Smrg return false; 13597ec681f3Smrg *value = (int)res_param; 13607ec681f3Smrg return true; 13617ec681f3Smrg case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: 13627ec681f3Smrg if (res_param == DRM_FORMAT_MOD_INVALID) 13637ec681f3Smrg return false; 13647ec681f3Smrg *value = (res_param >> 32) & 0xffffffff; 13657ec681f3Smrg return true; 13667ec681f3Smrg case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: 13677ec681f3Smrg if (res_param == DRM_FORMAT_MOD_INVALID) 13687ec681f3Smrg return false; 13697ec681f3Smrg *value = res_param & 0xffffffff; 13707ec681f3Smrg return true; 13717ec681f3Smrg default: 13727ec681f3Smrg return false; 13737ec681f3Smrg } 13747ec681f3Smrg} 13757ec681f3Smrg 13767ec681f3Smrgstatic GLboolean 13777ec681f3Smrgdri2_query_image(__DRIimage *image, int attrib, int *value) 13787ec681f3Smrg{ 13797ec681f3Smrg if (dri2_query_image_common(image, attrib, value)) 13807ec681f3Smrg return GL_TRUE; 13817ec681f3Smrg else if (dri2_query_image_by_resource_param(image, attrib, value)) 13827ec681f3Smrg return GL_TRUE; 13837ec681f3Smrg else if (dri2_query_image_by_resource_handle(image, attrib, value)) 13847ec681f3Smrg return GL_TRUE; 13857ec681f3Smrg else 13867ec681f3Smrg return GL_FALSE; 13877ec681f3Smrg} 13887ec681f3Smrg 13897ec681f3Smrgstatic __DRIimage * 13907ec681f3Smrgdri2_dup_image(__DRIimage *image, void *loaderPrivate) 13917ec681f3Smrg{ 13927ec681f3Smrg __DRIimage *img; 13937ec681f3Smrg 13947ec681f3Smrg img = CALLOC_STRUCT(__DRIimageRec); 13957ec681f3Smrg if (!img) 13967ec681f3Smrg return NULL; 13977ec681f3Smrg 13987ec681f3Smrg img->texture = NULL; 13997ec681f3Smrg pipe_resource_reference(&img->texture, image->texture); 14007ec681f3Smrg img->level = image->level; 14017ec681f3Smrg img->layer = image->layer; 14027ec681f3Smrg img->dri_format = image->dri_format; 14037ec681f3Smrg /* This should be 0 for sub images, but dup is also used for base images. */ 14047ec681f3Smrg img->dri_components = image->dri_components; 14057ec681f3Smrg img->use = image->use; 14067ec681f3Smrg img->loader_private = loaderPrivate; 14077ec681f3Smrg img->sPriv = image->sPriv; 14087ec681f3Smrg 14097ec681f3Smrg return img; 14107ec681f3Smrg} 14117ec681f3Smrg 14127ec681f3Smrgstatic GLboolean 14137ec681f3Smrgdri2_validate_usage(__DRIimage *image, unsigned int use) 14147ec681f3Smrg{ 14157ec681f3Smrg if (!image || !image->texture) 14167ec681f3Smrg return false; 14177ec681f3Smrg 14187ec681f3Smrg struct pipe_screen *screen = image->texture->screen; 14197ec681f3Smrg if (!screen->check_resource_capability) 14207ec681f3Smrg return true; 14217ec681f3Smrg 14227ec681f3Smrg /* We don't want to check these: 14237ec681f3Smrg * __DRI_IMAGE_USE_SHARE (all images are shareable) 14247ec681f3Smrg * __DRI_IMAGE_USE_BACKBUFFER (all images support this) 14257ec681f3Smrg */ 14267ec681f3Smrg unsigned bind = 0; 14277ec681f3Smrg if (use & __DRI_IMAGE_USE_SCANOUT) 14287ec681f3Smrg bind |= PIPE_BIND_SCANOUT; 14297ec681f3Smrg if (use & __DRI_IMAGE_USE_LINEAR) 14307ec681f3Smrg bind |= PIPE_BIND_LINEAR; 14317ec681f3Smrg if (use & __DRI_IMAGE_USE_CURSOR) 14327ec681f3Smrg bind |= PIPE_BIND_CURSOR; 14337ec681f3Smrg 14347ec681f3Smrg if (!bind) 14357ec681f3Smrg return true; 14367ec681f3Smrg 14377ec681f3Smrg return screen->check_resource_capability(screen, image->texture, bind); 14387ec681f3Smrg} 14397ec681f3Smrg 14407ec681f3Smrgstatic __DRIimage * 14417ec681f3Smrgdri2_from_names(__DRIscreen *screen, int width, int height, int format, 14427ec681f3Smrg int *names, int num_names, int *strides, int *offsets, 14437ec681f3Smrg void *loaderPrivate) 14447ec681f3Smrg{ 14457ec681f3Smrg const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); 14467ec681f3Smrg __DRIimage *img; 14477ec681f3Smrg struct winsys_handle whandle; 14487ec681f3Smrg 14497ec681f3Smrg if (!map) 14507ec681f3Smrg return NULL; 14517ec681f3Smrg 14527ec681f3Smrg if (num_names != 1) 14537ec681f3Smrg return NULL; 14547ec681f3Smrg 14557ec681f3Smrg memset(&whandle, 0, sizeof(whandle)); 14567ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_SHARED; 14577ec681f3Smrg whandle.handle = names[0]; 14587ec681f3Smrg whandle.stride = strides[0]; 14597ec681f3Smrg whandle.offset = offsets[0]; 14607ec681f3Smrg whandle.format = map->pipe_format; 14617ec681f3Smrg whandle.modifier = DRM_FORMAT_MOD_INVALID; 14627ec681f3Smrg 14637ec681f3Smrg img = dri2_create_image_from_winsys(screen, width, height, map, 14647ec681f3Smrg 1, &whandle, false, loaderPrivate); 14657ec681f3Smrg if (img == NULL) 14667ec681f3Smrg return NULL; 14677ec681f3Smrg 14687ec681f3Smrg img->dri_components = map->dri_components; 14697ec681f3Smrg img->dri_fourcc = map->dri_fourcc; 14707ec681f3Smrg img->dri_format = map->pipe_format; 14717ec681f3Smrg 14727ec681f3Smrg return img; 14737ec681f3Smrg} 14747ec681f3Smrg 14757ec681f3Smrgstatic __DRIimage * 14767ec681f3Smrgdri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) 14777ec681f3Smrg{ 14787ec681f3Smrg __DRIimage *img; 14797ec681f3Smrg 14807ec681f3Smrg if (plane < 0) { 14817ec681f3Smrg return NULL; 14827ec681f3Smrg } else if (plane > 0) { 14837ec681f3Smrg uint64_t planes; 14847ec681f3Smrg if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_NPLANES, 0, 14857ec681f3Smrg &planes) || 14867ec681f3Smrg plane >= planes) { 14877ec681f3Smrg return NULL; 14887ec681f3Smrg } 14897ec681f3Smrg } 14907ec681f3Smrg 14917ec681f3Smrg if (image->dri_components == 0) { 14927ec681f3Smrg uint64_t modifier; 14937ec681f3Smrg if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_MODIFIER, 0, 14947ec681f3Smrg &modifier) || 14957ec681f3Smrg modifier == DRM_FORMAT_MOD_INVALID) { 14967ec681f3Smrg return NULL; 14977ec681f3Smrg } 14987ec681f3Smrg } 14997ec681f3Smrg 15007ec681f3Smrg img = dri2_dup_image(image, loaderPrivate); 15017ec681f3Smrg if (img == NULL) 15027ec681f3Smrg return NULL; 15037ec681f3Smrg 15047ec681f3Smrg if (img->texture->screen->resource_changed) 15057ec681f3Smrg img->texture->screen->resource_changed(img->texture->screen, 15067ec681f3Smrg img->texture); 15077ec681f3Smrg 15087ec681f3Smrg /* set this to 0 for sub images. */ 15097ec681f3Smrg img->dri_components = 0; 15107ec681f3Smrg img->plane = plane; 15117ec681f3Smrg return img; 15127ec681f3Smrg} 15137ec681f3Smrg 15147ec681f3Smrgstatic __DRIimage * 15157ec681f3Smrgdri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc, 15167ec681f3Smrg int *fds, int num_fds, int *strides, int *offsets, 15177ec681f3Smrg void *loaderPrivate) 15187ec681f3Smrg{ 15197ec681f3Smrg return dri2_create_image_from_fd(screen, width, height, fourcc, 15207ec681f3Smrg DRM_FORMAT_MOD_INVALID, fds, num_fds, 15217ec681f3Smrg strides, offsets, false, NULL, loaderPrivate); 15227ec681f3Smrg} 15237ec681f3Smrg 15247ec681f3Smrgstatic boolean 15257ec681f3Smrgdri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max, 15267ec681f3Smrg uint64_t *modifiers, unsigned int *external_only, 15277ec681f3Smrg int *count) 15287ec681f3Smrg{ 15297ec681f3Smrg struct dri_screen *screen = dri_screen(_screen); 15307ec681f3Smrg struct pipe_screen *pscreen = screen->base.screen; 15317ec681f3Smrg const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); 15327ec681f3Smrg enum pipe_format format; 15337ec681f3Smrg 15347ec681f3Smrg if (!map) 15357ec681f3Smrg return false; 15367ec681f3Smrg 15377ec681f3Smrg format = map->pipe_format; 15387ec681f3Smrg 15397ec681f3Smrg bool native_sampling = pscreen->is_format_supported(pscreen, format, screen->target, 0, 0, 15407ec681f3Smrg PIPE_BIND_SAMPLER_VIEW); 15417ec681f3Smrg if (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0, 15427ec681f3Smrg PIPE_BIND_RENDER_TARGET) || 15437ec681f3Smrg native_sampling || 15447ec681f3Smrg dri2_yuv_dma_buf_supported(screen, map)) { 15457ec681f3Smrg if (pscreen->query_dmabuf_modifiers != NULL) { 15467ec681f3Smrg pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers, 15477ec681f3Smrg external_only, count); 15487ec681f3Smrg if (!native_sampling && external_only) { 15497ec681f3Smrg /* To support it using YUV lowering, we need it to be samplerExternalOES. 15507ec681f3Smrg */ 15517ec681f3Smrg for (int i = 0; i < *count; i++) 15527ec681f3Smrg external_only[i] = true; 15537ec681f3Smrg } 15547ec681f3Smrg } else { 15557ec681f3Smrg *count = 0; 15567ec681f3Smrg } 15577ec681f3Smrg return true; 15587ec681f3Smrg } 15597ec681f3Smrg return false; 15607ec681f3Smrg} 15617ec681f3Smrg 15627ec681f3Smrgstatic boolean 15637ec681f3Smrgdri2_query_dma_buf_format_modifier_attribs(__DRIscreen *_screen, 15647ec681f3Smrg uint32_t fourcc, uint64_t modifier, 15657ec681f3Smrg int attrib, uint64_t *value) 15667ec681f3Smrg{ 15677ec681f3Smrg struct dri_screen *screen = dri_screen(_screen); 15687ec681f3Smrg struct pipe_screen *pscreen = screen->base.screen; 15697ec681f3Smrg 15707ec681f3Smrg if (!pscreen->query_dmabuf_modifiers) 15717ec681f3Smrg return false; 15727ec681f3Smrg 15737ec681f3Smrg switch (attrib) { 15747ec681f3Smrg case __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: { 15757ec681f3Smrg uint64_t mod_planes = dri2_get_modifier_num_planes(_screen, modifier, 15767ec681f3Smrg fourcc); 15777ec681f3Smrg if (mod_planes > 0) 15787ec681f3Smrg *value = mod_planes; 15797ec681f3Smrg return mod_planes > 0; 15807ec681f3Smrg } 15817ec681f3Smrg default: 15827ec681f3Smrg return false; 15837ec681f3Smrg } 15847ec681f3Smrg} 15857ec681f3Smrg 15867ec681f3Smrgstatic __DRIimage * 15877ec681f3Smrgdri2_from_dma_bufs(__DRIscreen *screen, 15887ec681f3Smrg int width, int height, int fourcc, 15897ec681f3Smrg int *fds, int num_fds, 15907ec681f3Smrg int *strides, int *offsets, 15917ec681f3Smrg enum __DRIYUVColorSpace yuv_color_space, 15927ec681f3Smrg enum __DRISampleRange sample_range, 15937ec681f3Smrg enum __DRIChromaSiting horizontal_siting, 15947ec681f3Smrg enum __DRIChromaSiting vertical_siting, 15957ec681f3Smrg unsigned *error, 15967ec681f3Smrg void *loaderPrivate) 15977ec681f3Smrg{ 15987ec681f3Smrg __DRIimage *img; 15997ec681f3Smrg 16007ec681f3Smrg img = dri2_create_image_from_fd(screen, width, height, fourcc, 16017ec681f3Smrg DRM_FORMAT_MOD_INVALID, fds, num_fds, 16027ec681f3Smrg strides, offsets, false, error, loaderPrivate); 16037ec681f3Smrg if (img == NULL) 16047ec681f3Smrg return NULL; 16057ec681f3Smrg 16067ec681f3Smrg img->yuv_color_space = yuv_color_space; 16077ec681f3Smrg img->sample_range = sample_range; 16087ec681f3Smrg img->horizontal_siting = horizontal_siting; 16097ec681f3Smrg img->vertical_siting = vertical_siting; 16107ec681f3Smrg 16117ec681f3Smrg *error = __DRI_IMAGE_ERROR_SUCCESS; 16127ec681f3Smrg return img; 16137ec681f3Smrg} 16147ec681f3Smrg 16157ec681f3Smrgstatic __DRIimage * 16167ec681f3Smrgdri2_from_dma_bufs2(__DRIscreen *screen, 16177ec681f3Smrg int width, int height, int fourcc, 16187ec681f3Smrg uint64_t modifier, int *fds, int num_fds, 16197ec681f3Smrg int *strides, int *offsets, 16207ec681f3Smrg enum __DRIYUVColorSpace yuv_color_space, 16217ec681f3Smrg enum __DRISampleRange sample_range, 16227ec681f3Smrg enum __DRIChromaSiting horizontal_siting, 16237ec681f3Smrg enum __DRIChromaSiting vertical_siting, 16247ec681f3Smrg unsigned *error, 16257ec681f3Smrg void *loaderPrivate) 16267ec681f3Smrg{ 16277ec681f3Smrg __DRIimage *img; 16287ec681f3Smrg 16297ec681f3Smrg img = dri2_create_image_from_fd(screen, width, height, fourcc, 16307ec681f3Smrg modifier, fds, num_fds, strides, offsets, 16317ec681f3Smrg false, error, loaderPrivate); 16327ec681f3Smrg if (img == NULL) 16337ec681f3Smrg return NULL; 16347ec681f3Smrg 16357ec681f3Smrg img->yuv_color_space = yuv_color_space; 16367ec681f3Smrg img->sample_range = sample_range; 16377ec681f3Smrg img->horizontal_siting = horizontal_siting; 16387ec681f3Smrg img->vertical_siting = vertical_siting; 16397ec681f3Smrg 16407ec681f3Smrg *error = __DRI_IMAGE_ERROR_SUCCESS; 16417ec681f3Smrg return img; 16427ec681f3Smrg} 16437ec681f3Smrg 16447ec681f3Smrgstatic __DRIimage * 16457ec681f3Smrgdri2_from_dma_bufs3(__DRIscreen *screen, 16467ec681f3Smrg int width, int height, int fourcc, 16477ec681f3Smrg uint64_t modifier, int *fds, int num_fds, 16487ec681f3Smrg int *strides, int *offsets, 16497ec681f3Smrg enum __DRIYUVColorSpace yuv_color_space, 16507ec681f3Smrg enum __DRISampleRange sample_range, 16517ec681f3Smrg enum __DRIChromaSiting horizontal_siting, 16527ec681f3Smrg enum __DRIChromaSiting vertical_siting, 16537ec681f3Smrg uint32_t flags, 16547ec681f3Smrg unsigned *error, 16557ec681f3Smrg void *loaderPrivate) 16567ec681f3Smrg{ 16577ec681f3Smrg __DRIimage *img; 16587ec681f3Smrg 16597ec681f3Smrg img = dri2_create_image_from_fd(screen, width, height, fourcc, 16607ec681f3Smrg modifier, fds, num_fds, strides, offsets, 16617ec681f3Smrg flags & __DRI_IMAGE_PROTECTED_CONTENT_FLAG, 16627ec681f3Smrg error, loaderPrivate); 16637ec681f3Smrg if (img == NULL) 16647ec681f3Smrg return NULL; 16657ec681f3Smrg 16667ec681f3Smrg img->yuv_color_space = yuv_color_space; 16677ec681f3Smrg img->sample_range = sample_range; 16687ec681f3Smrg img->horizontal_siting = horizontal_siting; 16697ec681f3Smrg img->vertical_siting = vertical_siting; 16707ec681f3Smrg 16717ec681f3Smrg *error = __DRI_IMAGE_ERROR_SUCCESS; 16727ec681f3Smrg return img; 16737ec681f3Smrg} 16747ec681f3Smrg 16757ec681f3Smrgstatic void 16767ec681f3Smrgdri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src, 16777ec681f3Smrg int dstx0, int dsty0, int dstwidth, int dstheight, 16787ec681f3Smrg int srcx0, int srcy0, int srcwidth, int srcheight, 16797ec681f3Smrg int flush_flag) 16807ec681f3Smrg{ 16817ec681f3Smrg struct dri_context *ctx = dri_context(context); 16827ec681f3Smrg struct pipe_context *pipe = ctx->st->pipe; 16837ec681f3Smrg struct pipe_screen *screen; 16847ec681f3Smrg struct pipe_fence_handle *fence; 16857ec681f3Smrg struct pipe_blit_info blit; 16867ec681f3Smrg 16877ec681f3Smrg if (!dst || !src) 16887ec681f3Smrg return; 16897ec681f3Smrg 16907ec681f3Smrg memset(&blit, 0, sizeof(blit)); 16917ec681f3Smrg blit.dst.resource = dst->texture; 16927ec681f3Smrg blit.dst.box.x = dstx0; 16937ec681f3Smrg blit.dst.box.y = dsty0; 16947ec681f3Smrg blit.dst.box.width = dstwidth; 16957ec681f3Smrg blit.dst.box.height = dstheight; 16967ec681f3Smrg blit.dst.box.depth = 1; 16977ec681f3Smrg blit.dst.format = dst->texture->format; 16987ec681f3Smrg blit.src.resource = src->texture; 16997ec681f3Smrg blit.src.box.x = srcx0; 17007ec681f3Smrg blit.src.box.y = srcy0; 17017ec681f3Smrg blit.src.box.width = srcwidth; 17027ec681f3Smrg blit.src.box.height = srcheight; 17037ec681f3Smrg blit.src.box.depth = 1; 17047ec681f3Smrg blit.src.format = src->texture->format; 17057ec681f3Smrg blit.mask = PIPE_MASK_RGBA; 17067ec681f3Smrg blit.filter = PIPE_TEX_FILTER_NEAREST; 17077ec681f3Smrg blit.is_dri_blit_image = true; 17087ec681f3Smrg 17097ec681f3Smrg pipe->blit(pipe, &blit); 17107ec681f3Smrg 17117ec681f3Smrg if (flush_flag == __BLIT_FLAG_FLUSH) { 17127ec681f3Smrg pipe->flush_resource(pipe, dst->texture); 17137ec681f3Smrg ctx->st->flush(ctx->st, 0, NULL, NULL, NULL); 17147ec681f3Smrg } else if (flush_flag == __BLIT_FLAG_FINISH) { 17157ec681f3Smrg screen = dri_screen(ctx->sPriv)->base.screen; 17167ec681f3Smrg pipe->flush_resource(pipe, dst->texture); 17177ec681f3Smrg ctx->st->flush(ctx->st, 0, &fence, NULL, NULL); 17187ec681f3Smrg (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE); 17197ec681f3Smrg screen->fence_reference(screen, &fence, NULL); 17207ec681f3Smrg } 17217ec681f3Smrg} 17227ec681f3Smrg 17237ec681f3Smrgstatic void * 17247ec681f3Smrgdri2_map_image(__DRIcontext *context, __DRIimage *image, 17257ec681f3Smrg int x0, int y0, int width, int height, 17267ec681f3Smrg unsigned int flags, int *stride, void **data) 17277ec681f3Smrg{ 17287ec681f3Smrg struct dri_context *ctx = dri_context(context); 17297ec681f3Smrg struct pipe_context *pipe = ctx->st->pipe; 17307ec681f3Smrg enum pipe_map_flags pipe_access = 0; 17317ec681f3Smrg struct pipe_transfer *trans; 17327ec681f3Smrg void *map; 17337ec681f3Smrg 17347ec681f3Smrg if (!image || !data || *data) 17357ec681f3Smrg return NULL; 17367ec681f3Smrg 17377ec681f3Smrg unsigned plane = image->plane; 17387ec681f3Smrg if (plane >= dri2_get_mapping_by_format(image->dri_format)->nplanes) 17397ec681f3Smrg return NULL; 17407ec681f3Smrg 17417ec681f3Smrg struct pipe_resource *resource = image->texture; 17427ec681f3Smrg while (plane--) 17437ec681f3Smrg resource = resource->next; 17447ec681f3Smrg 17457ec681f3Smrg if (flags & __DRI_IMAGE_TRANSFER_READ) 17467ec681f3Smrg pipe_access |= PIPE_MAP_READ; 17477ec681f3Smrg if (flags & __DRI_IMAGE_TRANSFER_WRITE) 17487ec681f3Smrg pipe_access |= PIPE_MAP_WRITE; 17497ec681f3Smrg 17507ec681f3Smrg map = pipe_texture_map(pipe, resource, 0, 0, pipe_access, x0, y0, 17517ec681f3Smrg width, height, &trans); 17527ec681f3Smrg if (map) { 17537ec681f3Smrg *data = trans; 17547ec681f3Smrg *stride = trans->stride; 17557ec681f3Smrg } 17567ec681f3Smrg 17577ec681f3Smrg return map; 17587ec681f3Smrg} 17597ec681f3Smrg 17607ec681f3Smrgstatic void 17617ec681f3Smrgdri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data) 17627ec681f3Smrg{ 17637ec681f3Smrg struct dri_context *ctx = dri_context(context); 17647ec681f3Smrg struct pipe_context *pipe = ctx->st->pipe; 17657ec681f3Smrg 17667ec681f3Smrg pipe_texture_unmap(pipe, (struct pipe_transfer *)data); 17677ec681f3Smrg} 17687ec681f3Smrg 17697ec681f3Smrgstatic int 17707ec681f3Smrgdri2_get_capabilities(__DRIscreen *_screen) 17717ec681f3Smrg{ 17727ec681f3Smrg struct dri_screen *screen = dri_screen(_screen); 17737ec681f3Smrg 17747ec681f3Smrg return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0); 17757ec681f3Smrg} 17767ec681f3Smrg 17777ec681f3Smrg/* The extension is modified during runtime if DRI_PRIME is detected */ 17787ec681f3Smrgstatic const __DRIimageExtension dri2ImageExtensionTempl = { 17797ec681f3Smrg .base = { __DRI_IMAGE, 19 }, 17807ec681f3Smrg 17817ec681f3Smrg .createImageFromName = dri2_create_image_from_name, 17827ec681f3Smrg .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, 17837ec681f3Smrg .destroyImage = dri2_destroy_image, 17847ec681f3Smrg .createImage = dri2_create_image, 17857ec681f3Smrg .queryImage = dri2_query_image, 17867ec681f3Smrg .dupImage = dri2_dup_image, 17877ec681f3Smrg .validateUsage = dri2_validate_usage, 17887ec681f3Smrg .createImageFromNames = dri2_from_names, 17897ec681f3Smrg .fromPlanar = dri2_from_planar, 17907ec681f3Smrg .createImageFromTexture = dri2_create_from_texture, 17917ec681f3Smrg .createImageFromFds = NULL, 17927ec681f3Smrg .createImageFromDmaBufs = NULL, 17937ec681f3Smrg .blitImage = dri2_blit_image, 17947ec681f3Smrg .getCapabilities = dri2_get_capabilities, 17957ec681f3Smrg .mapImage = dri2_map_image, 17967ec681f3Smrg .unmapImage = dri2_unmap_image, 17977ec681f3Smrg .createImageWithModifiers = NULL, 17987ec681f3Smrg .createImageFromDmaBufs2 = NULL, 17997ec681f3Smrg .createImageFromDmaBufs3 = NULL, 18007ec681f3Smrg .queryDmaBufFormats = NULL, 18017ec681f3Smrg .queryDmaBufModifiers = NULL, 18027ec681f3Smrg .queryDmaBufFormatModifierAttribs = NULL, 18037ec681f3Smrg .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2, 18047ec681f3Smrg .createImageWithModifiers2 = NULL, 18057ec681f3Smrg}; 18067ec681f3Smrg 18077ec681f3Smrgstatic const __DRIrobustnessExtension dri2Robustness = { 18087ec681f3Smrg .base = { __DRI2_ROBUSTNESS, 1 } 18097ec681f3Smrg}; 18107ec681f3Smrg 18117ec681f3Smrgstatic int 18127ec681f3Smrgdri2_interop_query_device_info(__DRIcontext *_ctx, 18137ec681f3Smrg struct mesa_glinterop_device_info *out) 18147ec681f3Smrg{ 18157ec681f3Smrg struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen; 18167ec681f3Smrg 18177ec681f3Smrg /* There is no version 0, thus we do not support it */ 18187ec681f3Smrg if (out->version == 0) 18197ec681f3Smrg return MESA_GLINTEROP_INVALID_VERSION; 18207ec681f3Smrg 18217ec681f3Smrg out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP); 18227ec681f3Smrg out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS); 18237ec681f3Smrg out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE); 18247ec681f3Smrg out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION); 18257ec681f3Smrg 18267ec681f3Smrg out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID); 18277ec681f3Smrg out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID); 18287ec681f3Smrg 18297ec681f3Smrg /* Instruct the caller that we support up-to version one of the interface */ 18307ec681f3Smrg out->version = 1; 18317ec681f3Smrg 18327ec681f3Smrg return MESA_GLINTEROP_SUCCESS; 18337ec681f3Smrg} 18347ec681f3Smrg 18357ec681f3Smrgstatic int 18367ec681f3Smrgdri2_interop_export_object(__DRIcontext *_ctx, 18377ec681f3Smrg struct mesa_glinterop_export_in *in, 18387ec681f3Smrg struct mesa_glinterop_export_out *out) 18397ec681f3Smrg{ 18407ec681f3Smrg struct st_context_iface *st = dri_context(_ctx)->st; 18417ec681f3Smrg struct pipe_screen *screen = st->pipe->screen; 18427ec681f3Smrg struct gl_context *ctx = ((struct st_context *)st)->ctx; 18437ec681f3Smrg struct pipe_resource *res = NULL; 18447ec681f3Smrg struct winsys_handle whandle; 18457ec681f3Smrg unsigned target, usage; 18467ec681f3Smrg boolean success; 18477ec681f3Smrg 18487ec681f3Smrg /* There is no version 0, thus we do not support it */ 18497ec681f3Smrg if (in->version == 0 || out->version == 0) 18507ec681f3Smrg return MESA_GLINTEROP_INVALID_VERSION; 18517ec681f3Smrg 18527ec681f3Smrg /* Validate the target. */ 18537ec681f3Smrg switch (in->target) { 18547ec681f3Smrg case GL_TEXTURE_BUFFER: 18557ec681f3Smrg case GL_TEXTURE_1D: 18567ec681f3Smrg case GL_TEXTURE_2D: 18577ec681f3Smrg case GL_TEXTURE_3D: 18587ec681f3Smrg case GL_TEXTURE_RECTANGLE: 18597ec681f3Smrg case GL_TEXTURE_1D_ARRAY: 18607ec681f3Smrg case GL_TEXTURE_2D_ARRAY: 18617ec681f3Smrg case GL_TEXTURE_CUBE_MAP_ARRAY: 18627ec681f3Smrg case GL_TEXTURE_CUBE_MAP: 18637ec681f3Smrg case GL_TEXTURE_2D_MULTISAMPLE: 18647ec681f3Smrg case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 18657ec681f3Smrg case GL_TEXTURE_EXTERNAL_OES: 18667ec681f3Smrg case GL_RENDERBUFFER: 18677ec681f3Smrg case GL_ARRAY_BUFFER: 18687ec681f3Smrg target = in->target; 18697ec681f3Smrg break; 18707ec681f3Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 18717ec681f3Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 18727ec681f3Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 18737ec681f3Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 18747ec681f3Smrg case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 18757ec681f3Smrg case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 18767ec681f3Smrg target = GL_TEXTURE_CUBE_MAP; 18777ec681f3Smrg break; 18787ec681f3Smrg default: 18797ec681f3Smrg return MESA_GLINTEROP_INVALID_TARGET; 18807ec681f3Smrg } 18817ec681f3Smrg 18827ec681f3Smrg /* Validate the simple case of miplevel. */ 18837ec681f3Smrg if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) && 18847ec681f3Smrg in->miplevel != 0) 18857ec681f3Smrg return MESA_GLINTEROP_INVALID_MIP_LEVEL; 18867ec681f3Smrg 18877ec681f3Smrg /* Validate the OpenGL object and get pipe_resource. */ 18887ec681f3Smrg simple_mtx_lock(&ctx->Shared->Mutex); 18897ec681f3Smrg 18907ec681f3Smrg if (target == GL_ARRAY_BUFFER) { 18917ec681f3Smrg /* Buffer objects. 18927ec681f3Smrg * 18937ec681f3Smrg * The error checking is based on the documentation of 18947ec681f3Smrg * clCreateFromGLBuffer from OpenCL 2.0 SDK. 18957ec681f3Smrg */ 18967ec681f3Smrg struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj); 18977ec681f3Smrg 18987ec681f3Smrg /* From OpenCL 2.0 SDK, clCreateFromGLBuffer: 18997ec681f3Smrg * "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is 19007ec681f3Smrg * a GL buffer object but does not have an existing data store or 19017ec681f3Smrg * the size of the buffer is 0." 19027ec681f3Smrg */ 19037ec681f3Smrg if (!buf || buf->Size == 0) { 19047ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 19057ec681f3Smrg return MESA_GLINTEROP_INVALID_OBJECT; 19067ec681f3Smrg } 19077ec681f3Smrg 19087ec681f3Smrg res = st_buffer_object(buf)->buffer; 19097ec681f3Smrg if (!res) { 19107ec681f3Smrg /* this shouldn't happen */ 19117ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 19127ec681f3Smrg return MESA_GLINTEROP_INVALID_OBJECT; 19137ec681f3Smrg } 19147ec681f3Smrg 19157ec681f3Smrg out->buf_offset = 0; 19167ec681f3Smrg out->buf_size = buf->Size; 19177ec681f3Smrg 19187ec681f3Smrg buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; 19197ec681f3Smrg } else if (target == GL_RENDERBUFFER) { 19207ec681f3Smrg /* Renderbuffers. 19217ec681f3Smrg * 19227ec681f3Smrg * The error checking is based on the documentation of 19237ec681f3Smrg * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK. 19247ec681f3Smrg */ 19257ec681f3Smrg struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj); 19267ec681f3Smrg 19277ec681f3Smrg /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: 19287ec681f3Smrg * "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer 19297ec681f3Smrg * object or if the width or height of renderbuffer is zero." 19307ec681f3Smrg */ 19317ec681f3Smrg if (!rb || rb->Width == 0 || rb->Height == 0) { 19327ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 19337ec681f3Smrg return MESA_GLINTEROP_INVALID_OBJECT; 19347ec681f3Smrg } 19357ec681f3Smrg 19367ec681f3Smrg /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: 19377ec681f3Smrg * "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL 19387ec681f3Smrg * renderbuffer object." 19397ec681f3Smrg */ 19407ec681f3Smrg if (rb->NumSamples > 1) { 19417ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 19427ec681f3Smrg return MESA_GLINTEROP_INVALID_OPERATION; 19437ec681f3Smrg } 19447ec681f3Smrg 19457ec681f3Smrg /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: 19467ec681f3Smrg * "CL_OUT_OF_RESOURCES if there is a failure to allocate resources 19477ec681f3Smrg * required by the OpenCL implementation on the device." 19487ec681f3Smrg */ 19497ec681f3Smrg res = st_renderbuffer(rb)->texture; 19507ec681f3Smrg if (!res) { 19517ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 19527ec681f3Smrg return MESA_GLINTEROP_OUT_OF_RESOURCES; 19537ec681f3Smrg } 19547ec681f3Smrg 19557ec681f3Smrg out->internal_format = rb->InternalFormat; 19567ec681f3Smrg out->view_minlevel = 0; 19577ec681f3Smrg out->view_numlevels = 1; 19587ec681f3Smrg out->view_minlayer = 0; 19597ec681f3Smrg out->view_numlayers = 1; 19607ec681f3Smrg } else { 19617ec681f3Smrg /* Texture objects. 19627ec681f3Smrg * 19637ec681f3Smrg * The error checking is based on the documentation of 19647ec681f3Smrg * clCreateFromGLTexture from OpenCL 2.0 SDK. 19657ec681f3Smrg */ 19667ec681f3Smrg struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj); 19677ec681f3Smrg 19687ec681f3Smrg if (obj) 19697ec681f3Smrg _mesa_test_texobj_completeness(ctx, obj); 19707ec681f3Smrg 19717ec681f3Smrg /* From OpenCL 2.0 SDK, clCreateFromGLTexture: 19727ec681f3Smrg * "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose 19737ec681f3Smrg * type matches texture_target, if the specified miplevel of texture 19747ec681f3Smrg * is not defined, or if the width or height of the specified 19757ec681f3Smrg * miplevel is zero or if the GL texture object is incomplete." 19767ec681f3Smrg */ 19777ec681f3Smrg if (!obj || 19787ec681f3Smrg obj->Target != target || 19797ec681f3Smrg !obj->_BaseComplete || 19807ec681f3Smrg (in->miplevel > 0 && !obj->_MipmapComplete)) { 19817ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 19827ec681f3Smrg return MESA_GLINTEROP_INVALID_OBJECT; 19837ec681f3Smrg } 19847ec681f3Smrg 19857ec681f3Smrg if (target == GL_TEXTURE_BUFFER) { 19867ec681f3Smrg struct st_buffer_object *stBuf = 19877ec681f3Smrg st_buffer_object(obj->BufferObject); 19887ec681f3Smrg 19897ec681f3Smrg if (!stBuf || !stBuf->buffer) { 19907ec681f3Smrg /* this shouldn't happen */ 19917ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 19927ec681f3Smrg return MESA_GLINTEROP_INVALID_OBJECT; 19937ec681f3Smrg } 19947ec681f3Smrg res = stBuf->buffer; 19957ec681f3Smrg 19967ec681f3Smrg out->internal_format = obj->BufferObjectFormat; 19977ec681f3Smrg out->buf_offset = obj->BufferOffset; 19987ec681f3Smrg out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size : 19997ec681f3Smrg obj->BufferSize; 20007ec681f3Smrg 20017ec681f3Smrg obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; 20027ec681f3Smrg } else { 20037ec681f3Smrg /* From OpenCL 2.0 SDK, clCreateFromGLTexture: 20047ec681f3Smrg * "CL_INVALID_MIP_LEVEL if miplevel is less than the value of 20057ec681f3Smrg * levelbase (for OpenGL implementations) or zero (for OpenGL ES 20067ec681f3Smrg * implementations); or greater than the value of q (for both OpenGL 20077ec681f3Smrg * and OpenGL ES). levelbase and q are defined for the texture in 20087ec681f3Smrg * section 3.8.10 (Texture Completeness) of the OpenGL 2.1 20097ec681f3Smrg * specification and section 3.7.10 of the OpenGL ES 2.0." 20107ec681f3Smrg */ 20117ec681f3Smrg if (in->miplevel < obj->Attrib.BaseLevel || in->miplevel > obj->_MaxLevel) { 20127ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 20137ec681f3Smrg return MESA_GLINTEROP_INVALID_MIP_LEVEL; 20147ec681f3Smrg } 20157ec681f3Smrg 20167ec681f3Smrg if (!st_finalize_texture(ctx, st->pipe, obj, 0)) { 20177ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 20187ec681f3Smrg return MESA_GLINTEROP_OUT_OF_RESOURCES; 20197ec681f3Smrg } 20207ec681f3Smrg 20217ec681f3Smrg res = st_get_texobj_resource(obj); 20227ec681f3Smrg if (!res) { 20237ec681f3Smrg /* Incomplete texture buffer object? This shouldn't really occur. */ 20247ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 20257ec681f3Smrg return MESA_GLINTEROP_INVALID_OBJECT; 20267ec681f3Smrg } 20277ec681f3Smrg 20287ec681f3Smrg out->internal_format = obj->Image[0][0]->InternalFormat; 20297ec681f3Smrg out->view_minlevel = obj->Attrib.MinLevel; 20307ec681f3Smrg out->view_numlevels = obj->Attrib.NumLevels; 20317ec681f3Smrg out->view_minlayer = obj->Attrib.MinLayer; 20327ec681f3Smrg out->view_numlayers = obj->Attrib.NumLayers; 20337ec681f3Smrg } 20347ec681f3Smrg } 20357ec681f3Smrg 20367ec681f3Smrg /* Get the handle. */ 20377ec681f3Smrg switch (in->access) { 20387ec681f3Smrg case MESA_GLINTEROP_ACCESS_READ_ONLY: 20397ec681f3Smrg usage = 0; 20407ec681f3Smrg break; 20417ec681f3Smrg case MESA_GLINTEROP_ACCESS_READ_WRITE: 20427ec681f3Smrg case MESA_GLINTEROP_ACCESS_WRITE_ONLY: 20437ec681f3Smrg usage = PIPE_HANDLE_USAGE_SHADER_WRITE; 20447ec681f3Smrg break; 20457ec681f3Smrg default: 20467ec681f3Smrg usage = 0; 20477ec681f3Smrg } 20487ec681f3Smrg 20497ec681f3Smrg memset(&whandle, 0, sizeof(whandle)); 20507ec681f3Smrg whandle.type = WINSYS_HANDLE_TYPE_FD; 20517ec681f3Smrg 20527ec681f3Smrg success = screen->resource_get_handle(screen, st->pipe, res, &whandle, 20537ec681f3Smrg usage); 20547ec681f3Smrg simple_mtx_unlock(&ctx->Shared->Mutex); 20557ec681f3Smrg 20567ec681f3Smrg if (!success) 20577ec681f3Smrg return MESA_GLINTEROP_OUT_OF_HOST_MEMORY; 20587ec681f3Smrg 20597ec681f3Smrg out->dmabuf_fd = whandle.handle; 20607ec681f3Smrg out->out_driver_data_written = 0; 20617ec681f3Smrg 20627ec681f3Smrg if (res->target == PIPE_BUFFER) 20637ec681f3Smrg out->buf_offset += whandle.offset; 20647ec681f3Smrg 20657ec681f3Smrg /* Instruct the caller that we support up-to version one of the interface */ 20667ec681f3Smrg in->version = 1; 20677ec681f3Smrg out->version = 1; 20687ec681f3Smrg 20697ec681f3Smrg return MESA_GLINTEROP_SUCCESS; 20707ec681f3Smrg} 20717ec681f3Smrg 20727ec681f3Smrgstatic const __DRI2interopExtension dri2InteropExtension = { 20737ec681f3Smrg .base = { __DRI2_INTEROP, 1 }, 20747ec681f3Smrg .query_device_info = dri2_interop_query_device_info, 20757ec681f3Smrg .export_object = dri2_interop_export_object 20767ec681f3Smrg}; 20777ec681f3Smrg 20787ec681f3Smrg/** 20797ec681f3Smrg * \brief the DRI2bufferDamageExtension set_damage_region method 20807ec681f3Smrg */ 20817ec681f3Smrgstatic void 20827ec681f3Smrgdri2_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects) 20837ec681f3Smrg{ 20847ec681f3Smrg struct dri_drawable *drawable = dri_drawable(dPriv); 20857ec681f3Smrg struct pipe_box *boxes = NULL; 20867ec681f3Smrg 20877ec681f3Smrg if (nrects) { 20887ec681f3Smrg boxes = CALLOC(nrects, sizeof(*boxes)); 20897ec681f3Smrg assert(boxes); 20907ec681f3Smrg 20917ec681f3Smrg for (unsigned int i = 0; i < nrects; i++) { 20927ec681f3Smrg int *rect = &rects[i * 4]; 20937ec681f3Smrg 20947ec681f3Smrg u_box_2d(rect[0], rect[1], rect[2], rect[3], &boxes[i]); 20957ec681f3Smrg } 20967ec681f3Smrg } 20977ec681f3Smrg 20987ec681f3Smrg FREE(drawable->damage_rects); 20997ec681f3Smrg drawable->damage_rects = boxes; 21007ec681f3Smrg drawable->num_damage_rects = nrects; 21017ec681f3Smrg 21027ec681f3Smrg /* Only apply the damage region if the BACK_LEFT texture is up-to-date. */ 21037ec681f3Smrg if (drawable->texture_stamp == drawable->dPriv->lastStamp && 21047ec681f3Smrg (drawable->texture_mask & (1 << ST_ATTACHMENT_BACK_LEFT))) { 21057ec681f3Smrg struct pipe_screen *screen = drawable->screen->base.screen; 21067ec681f3Smrg struct pipe_resource *resource; 21077ec681f3Smrg 21087ec681f3Smrg if (drawable->stvis.samples > 1) 21097ec681f3Smrg resource = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; 21107ec681f3Smrg else 21117ec681f3Smrg resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; 21127ec681f3Smrg 21137ec681f3Smrg screen->set_damage_region(screen, resource, 21147ec681f3Smrg drawable->num_damage_rects, 21157ec681f3Smrg drawable->damage_rects); 21167ec681f3Smrg } 21177ec681f3Smrg} 21187ec681f3Smrg 21197ec681f3Smrgstatic const __DRI2bufferDamageExtension dri2BufferDamageExtensionTempl = { 21207ec681f3Smrg .base = { __DRI2_BUFFER_DAMAGE, 1 }, 21217ec681f3Smrg}; 21227ec681f3Smrg 21237ec681f3Smrg/** 21247ec681f3Smrg * \brief the DRI2ConfigQueryExtension configQueryb method 21257ec681f3Smrg */ 21267ec681f3Smrgstatic int 21277ec681f3Smrgdri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var, 21287ec681f3Smrg unsigned char *val) 21297ec681f3Smrg{ 21307ec681f3Smrg struct dri_screen *screen = dri_screen(sPriv); 21317ec681f3Smrg 21327ec681f3Smrg if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL)) 21337ec681f3Smrg return dri2ConfigQueryExtension.configQueryb(sPriv, var, val); 21347ec681f3Smrg 21357ec681f3Smrg *val = driQueryOptionb(&screen->dev->option_cache, var); 21367ec681f3Smrg 21377ec681f3Smrg return 0; 21387ec681f3Smrg} 21397ec681f3Smrg 21407ec681f3Smrg/** 21417ec681f3Smrg * \brief the DRI2ConfigQueryExtension configQueryi method 21427ec681f3Smrg */ 21437ec681f3Smrgstatic int 21447ec681f3Smrgdri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val) 21457ec681f3Smrg{ 21467ec681f3Smrg struct dri_screen *screen = dri_screen(sPriv); 21477ec681f3Smrg 21487ec681f3Smrg if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) && 21497ec681f3Smrg !driCheckOption(&screen->dev->option_cache, var, DRI_ENUM)) 21507ec681f3Smrg return dri2ConfigQueryExtension.configQueryi(sPriv, var, val); 21517ec681f3Smrg 21527ec681f3Smrg *val = driQueryOptioni(&screen->dev->option_cache, var); 21537ec681f3Smrg 21547ec681f3Smrg return 0; 21557ec681f3Smrg} 21567ec681f3Smrg 21577ec681f3Smrg/** 21587ec681f3Smrg * \brief the DRI2ConfigQueryExtension configQueryf method 21597ec681f3Smrg */ 21607ec681f3Smrgstatic int 21617ec681f3Smrgdri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val) 21627ec681f3Smrg{ 21637ec681f3Smrg struct dri_screen *screen = dri_screen(sPriv); 21647ec681f3Smrg 21657ec681f3Smrg if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT)) 21667ec681f3Smrg return dri2ConfigQueryExtension.configQueryf(sPriv, var, val); 21677ec681f3Smrg 21687ec681f3Smrg *val = driQueryOptionf(&screen->dev->option_cache, var); 21697ec681f3Smrg 21707ec681f3Smrg return 0; 21717ec681f3Smrg} 21727ec681f3Smrg 21737ec681f3Smrg/** 21747ec681f3Smrg * \brief the DRI2ConfigQueryExtension configQuerys method 21757ec681f3Smrg */ 21767ec681f3Smrgstatic int 21777ec681f3Smrgdri2GalliumConfigQuerys(__DRIscreen *sPriv, const char *var, char **val) 21787ec681f3Smrg{ 21797ec681f3Smrg struct dri_screen *screen = dri_screen(sPriv); 21807ec681f3Smrg 21817ec681f3Smrg if (!driCheckOption(&screen->dev->option_cache, var, DRI_STRING)) 21827ec681f3Smrg return dri2ConfigQueryExtension.configQuerys(sPriv, var, val); 21837ec681f3Smrg 21847ec681f3Smrg *val = driQueryOptionstr(&screen->dev->option_cache, var); 21857ec681f3Smrg 21867ec681f3Smrg return 0; 21877ec681f3Smrg} 21887ec681f3Smrg 21897ec681f3Smrg/** 21907ec681f3Smrg * \brief the DRI2ConfigQueryExtension struct. 21917ec681f3Smrg * 21927ec681f3Smrg * We first query the driver option cache. Then the dri2 option cache. 21937ec681f3Smrg */ 21947ec681f3Smrgstatic const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = { 21957ec681f3Smrg .base = { __DRI2_CONFIG_QUERY, 2 }, 21967ec681f3Smrg 21977ec681f3Smrg .configQueryb = dri2GalliumConfigQueryb, 21987ec681f3Smrg .configQueryi = dri2GalliumConfigQueryi, 21997ec681f3Smrg .configQueryf = dri2GalliumConfigQueryf, 22007ec681f3Smrg .configQuerys = dri2GalliumConfigQuerys, 22017ec681f3Smrg}; 22027ec681f3Smrg 22037ec681f3Smrg/** 22047ec681f3Smrg * \brief the DRI2blobExtension set_cache_funcs method 22057ec681f3Smrg */ 22067ec681f3Smrgstatic void 22077ec681f3Smrgset_blob_cache_funcs(__DRIscreen *sPriv, __DRIblobCacheSet set, 22087ec681f3Smrg __DRIblobCacheGet get) 22097ec681f3Smrg{ 22107ec681f3Smrg struct dri_screen *screen = dri_screen(sPriv); 22117ec681f3Smrg struct pipe_screen *pscreen = screen->base.screen; 22127ec681f3Smrg 22137ec681f3Smrg if (!pscreen->get_disk_shader_cache) 22147ec681f3Smrg return; 22157ec681f3Smrg 22167ec681f3Smrg struct disk_cache *cache = pscreen->get_disk_shader_cache(pscreen); 22177ec681f3Smrg 22187ec681f3Smrg if (!cache) 22197ec681f3Smrg return; 22207ec681f3Smrg 22217ec681f3Smrg disk_cache_set_callbacks(cache, set, get); 22227ec681f3Smrg} 22237ec681f3Smrg 22247ec681f3Smrgstatic const __DRI2blobExtension driBlobExtension = { 22257ec681f3Smrg .base = { __DRI2_BLOB, 1 }, 22267ec681f3Smrg .set_cache_funcs = set_blob_cache_funcs 22277ec681f3Smrg}; 22287ec681f3Smrg 22297ec681f3Smrgstatic const __DRImutableRenderBufferDriverExtension driMutableRenderBufferExtension = { 22307ec681f3Smrg .base = { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1 }, 22317ec681f3Smrg}; 22327ec681f3Smrg 22337ec681f3Smrg/* 22347ec681f3Smrg * Backend function init_screen. 22357ec681f3Smrg */ 22367ec681f3Smrg 22377ec681f3Smrgstatic const __DRIextension *dri_screen_extensions_base[] = { 22387ec681f3Smrg &driTexBufferExtension.base, 22397ec681f3Smrg &dri2FlushExtension.base, 22407ec681f3Smrg &dri2RendererQueryExtension.base, 22417ec681f3Smrg &dri2GalliumConfigQueryExtension.base, 22427ec681f3Smrg &dri2ThrottleExtension.base, 22437ec681f3Smrg &dri2FenceExtension.base, 22447ec681f3Smrg &dri2InteropExtension.base, 22457ec681f3Smrg &dri2NoErrorExtension.base, 22467ec681f3Smrg &driBlobExtension.base, 22477ec681f3Smrg &driMutableRenderBufferExtension.base, 22487ec681f3Smrg}; 22497ec681f3Smrg 22507ec681f3Smrg/** 22517ec681f3Smrg * Set up the DRI extension list for this screen based on its underlying 22527ec681f3Smrg * gallium screen's capabilities. 22537ec681f3Smrg */ 22547ec681f3Smrgstatic void 22557ec681f3Smrgdri2_init_screen_extensions(struct dri_screen *screen, 22567ec681f3Smrg struct pipe_screen *pscreen, 22577ec681f3Smrg bool is_kms_screen) 22587ec681f3Smrg{ 22597ec681f3Smrg const __DRIextension **nExt; 22607ec681f3Smrg 22617ec681f3Smrg STATIC_ASSERT(sizeof(screen->screen_extensions) >= 22627ec681f3Smrg sizeof(dri_screen_extensions_base)); 22637ec681f3Smrg memcpy(&screen->screen_extensions, dri_screen_extensions_base, 22647ec681f3Smrg sizeof(dri_screen_extensions_base)); 22657ec681f3Smrg screen->sPriv->extensions = screen->screen_extensions; 22667ec681f3Smrg 22677ec681f3Smrg /* Point nExt at the end of the extension list */ 22687ec681f3Smrg nExt = &screen->screen_extensions[ARRAY_SIZE(dri_screen_extensions_base)]; 22697ec681f3Smrg 22707ec681f3Smrg screen->image_extension = dri2ImageExtensionTempl; 22717ec681f3Smrg if (pscreen->resource_create_with_modifiers) { 22727ec681f3Smrg screen->image_extension.createImageWithModifiers = 22737ec681f3Smrg dri2_create_image_with_modifiers; 22747ec681f3Smrg screen->image_extension.createImageWithModifiers2 = 22757ec681f3Smrg dri2_create_image_with_modifiers2; 22767ec681f3Smrg } 22777ec681f3Smrg 22787ec681f3Smrg if (pscreen->get_param(pscreen, PIPE_CAP_DMABUF)) { 22797ec681f3Smrg uint64_t cap; 22807ec681f3Smrg 22817ec681f3Smrg if (drmGetCap(screen->sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && 22827ec681f3Smrg (cap & DRM_PRIME_CAP_IMPORT)) { 22837ec681f3Smrg screen->image_extension.createImageFromFds = dri2_from_fds; 22847ec681f3Smrg screen->image_extension.createImageFromDmaBufs = dri2_from_dma_bufs; 22857ec681f3Smrg screen->image_extension.createImageFromDmaBufs2 = dri2_from_dma_bufs2; 22867ec681f3Smrg screen->image_extension.createImageFromDmaBufs3 = dri2_from_dma_bufs3; 22877ec681f3Smrg screen->image_extension.queryDmaBufFormats = 22887ec681f3Smrg dri2_query_dma_buf_formats; 22897ec681f3Smrg screen->image_extension.queryDmaBufModifiers = 22907ec681f3Smrg dri2_query_dma_buf_modifiers; 22917ec681f3Smrg if (!is_kms_screen) { 22927ec681f3Smrg screen->image_extension.queryDmaBufFormatModifierAttribs = 22937ec681f3Smrg dri2_query_dma_buf_format_modifier_attribs; 22947ec681f3Smrg } 22957ec681f3Smrg } 22967ec681f3Smrg } 22977ec681f3Smrg *nExt++ = &screen->image_extension.base; 22987ec681f3Smrg 22997ec681f3Smrg if (!is_kms_screen) { 23007ec681f3Smrg screen->buffer_damage_extension = dri2BufferDamageExtensionTempl; 23017ec681f3Smrg if (pscreen->set_damage_region) 23027ec681f3Smrg screen->buffer_damage_extension.set_damage_region = 23037ec681f3Smrg dri2_set_damage_region; 23047ec681f3Smrg *nExt++ = &screen->buffer_damage_extension.base; 23057ec681f3Smrg 23067ec681f3Smrg if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) { 23077ec681f3Smrg *nExt++ = &dri2Robustness.base; 23087ec681f3Smrg screen->has_reset_status_query = true; 23097ec681f3Smrg } 23107ec681f3Smrg } 23117ec681f3Smrg 23127ec681f3Smrg /* Ensure the extension list didn't overrun its buffer and is still 23137ec681f3Smrg * NULL-terminated */ 23147ec681f3Smrg assert(nExt - screen->screen_extensions <= 23157ec681f3Smrg ARRAY_SIZE(screen->screen_extensions) - 1); 23167ec681f3Smrg assert(!*nExt); 23177ec681f3Smrg} 23187ec681f3Smrg 23197ec681f3Smrg/** 23207ec681f3Smrg * This is the driver specific part of the createNewScreen entry point. 23217ec681f3Smrg * 23227ec681f3Smrg * Returns the struct gl_config supported by this driver. 23237ec681f3Smrg */ 23247ec681f3Smrgstatic const __DRIconfig ** 23257ec681f3Smrgdri2_init_screen(__DRIscreen * sPriv) 23267ec681f3Smrg{ 23277ec681f3Smrg const __DRIconfig **configs; 23287ec681f3Smrg struct dri_screen *screen; 23297ec681f3Smrg struct pipe_screen *pscreen = NULL; 23307ec681f3Smrg 23317ec681f3Smrg screen = CALLOC_STRUCT(dri_screen); 23327ec681f3Smrg if (!screen) 23337ec681f3Smrg return NULL; 23347ec681f3Smrg 23357ec681f3Smrg screen->sPriv = sPriv; 23367ec681f3Smrg screen->fd = sPriv->fd; 23377ec681f3Smrg (void) mtx_init(&screen->opencl_func_mutex, mtx_plain); 23387ec681f3Smrg 23397ec681f3Smrg sPriv->driverPrivate = (void *)screen; 23407ec681f3Smrg 23417ec681f3Smrg if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) { 23427ec681f3Smrg pscreen = pipe_loader_create_screen(screen->dev); 23437ec681f3Smrg dri_init_options(screen); 23447ec681f3Smrg } 23457ec681f3Smrg 23467ec681f3Smrg if (!pscreen) 23477ec681f3Smrg goto release_pipe; 23487ec681f3Smrg 23497ec681f3Smrg screen->throttle = pscreen->get_param(pscreen, PIPE_CAP_THROTTLE); 23507ec681f3Smrg 23517ec681f3Smrg dri2_init_screen_extensions(screen, pscreen, false); 23527ec681f3Smrg 23537ec681f3Smrg configs = dri_init_screen_helper(screen, pscreen); 23547ec681f3Smrg if (!configs) 23557ec681f3Smrg goto destroy_screen; 23567ec681f3Smrg 23577ec681f3Smrg screen->can_share_buffer = true; 23587ec681f3Smrg screen->auto_fake_front = dri_with_format(sPriv); 23597ec681f3Smrg screen->broken_invalidate = !sPriv->dri2.useInvalidate; 23607ec681f3Smrg screen->lookup_egl_image = dri2_lookup_egl_image; 23617ec681f3Smrg 23627ec681f3Smrg const __DRIimageLookupExtension *loader = sPriv->dri2.image; 23637ec681f3Smrg if (loader && 23647ec681f3Smrg loader->base.version >= 2 && 23657ec681f3Smrg loader->validateEGLImage && 23667ec681f3Smrg loader->lookupEGLImageValidated) { 23677ec681f3Smrg screen->validate_egl_image = dri2_validate_egl_image; 23687ec681f3Smrg screen->lookup_egl_image_validated = dri2_lookup_egl_image_validated; 23697ec681f3Smrg } 23707ec681f3Smrg 23717ec681f3Smrg return configs; 23727ec681f3Smrg 23737ec681f3Smrgdestroy_screen: 23747ec681f3Smrg dri_destroy_screen_helper(screen); 23757ec681f3Smrg 23767ec681f3Smrgrelease_pipe: 23777ec681f3Smrg if (screen->dev) 23787ec681f3Smrg pipe_loader_release(&screen->dev, 1); 23797ec681f3Smrg 23807ec681f3Smrg FREE(screen); 23817ec681f3Smrg return NULL; 23827ec681f3Smrg} 23837ec681f3Smrg 23847ec681f3Smrg/** 23857ec681f3Smrg * This is the driver specific part of the createNewScreen entry point. 23867ec681f3Smrg * 23877ec681f3Smrg * Returns the struct gl_config supported by this driver. 23887ec681f3Smrg */ 23897ec681f3Smrgstatic const __DRIconfig ** 23907ec681f3Smrgdri_kms_init_screen(__DRIscreen * sPriv) 23917ec681f3Smrg{ 23927ec681f3Smrg#if defined(GALLIUM_SOFTPIPE) 23937ec681f3Smrg const __DRIconfig **configs; 23947ec681f3Smrg struct dri_screen *screen; 23957ec681f3Smrg struct pipe_screen *pscreen = NULL; 23967ec681f3Smrg 23977ec681f3Smrg screen = CALLOC_STRUCT(dri_screen); 23987ec681f3Smrg if (!screen) 23997ec681f3Smrg return NULL; 24007ec681f3Smrg 24017ec681f3Smrg screen->sPriv = sPriv; 24027ec681f3Smrg screen->fd = sPriv->fd; 24037ec681f3Smrg 24047ec681f3Smrg sPriv->driverPrivate = (void *)screen; 24057ec681f3Smrg 24067ec681f3Smrg if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd)) { 24077ec681f3Smrg pscreen = pipe_loader_create_screen(screen->dev); 24087ec681f3Smrg dri_init_options(screen); 24097ec681f3Smrg } 24107ec681f3Smrg 24117ec681f3Smrg if (!pscreen) 24127ec681f3Smrg goto release_pipe; 24137ec681f3Smrg 24147ec681f3Smrg dri2_init_screen_extensions(screen, pscreen, true); 24157ec681f3Smrg 24167ec681f3Smrg configs = dri_init_screen_helper(screen, pscreen); 24177ec681f3Smrg if (!configs) 24187ec681f3Smrg goto destroy_screen; 24197ec681f3Smrg 24207ec681f3Smrg screen->can_share_buffer = false; 24217ec681f3Smrg screen->auto_fake_front = dri_with_format(sPriv); 24227ec681f3Smrg screen->broken_invalidate = !sPriv->dri2.useInvalidate; 24237ec681f3Smrg screen->lookup_egl_image = dri2_lookup_egl_image; 24247ec681f3Smrg 24257ec681f3Smrg const __DRIimageLookupExtension *loader = sPriv->dri2.image; 24267ec681f3Smrg if (loader && 24277ec681f3Smrg loader->base.version >= 2 && 24287ec681f3Smrg loader->validateEGLImage && 24297ec681f3Smrg loader->lookupEGLImageValidated) { 24307ec681f3Smrg screen->validate_egl_image = dri2_validate_egl_image; 24317ec681f3Smrg screen->lookup_egl_image_validated = dri2_lookup_egl_image_validated; 24327ec681f3Smrg } 24337ec681f3Smrg 24347ec681f3Smrg return configs; 24357ec681f3Smrg 24367ec681f3Smrgdestroy_screen: 24377ec681f3Smrg dri_destroy_screen_helper(screen); 24387ec681f3Smrg 24397ec681f3Smrgrelease_pipe: 24407ec681f3Smrg if (screen->dev) 24417ec681f3Smrg pipe_loader_release(&screen->dev, 1); 24427ec681f3Smrg 24437ec681f3Smrg FREE(screen); 24447ec681f3Smrg#endif // GALLIUM_SOFTPIPE 24457ec681f3Smrg return NULL; 24467ec681f3Smrg} 24477ec681f3Smrg 24487ec681f3Smrgstatic boolean 24497ec681f3Smrgdri2_create_buffer(__DRIscreen * sPriv, 24507ec681f3Smrg __DRIdrawable * dPriv, 24517ec681f3Smrg const struct gl_config * visual, boolean isPixmap) 24527ec681f3Smrg{ 24537ec681f3Smrg struct dri_drawable *drawable = NULL; 24547ec681f3Smrg 24557ec681f3Smrg if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) 24567ec681f3Smrg return FALSE; 24577ec681f3Smrg 24587ec681f3Smrg drawable = dPriv->driverPrivate; 24597ec681f3Smrg 24607ec681f3Smrg drawable->allocate_textures = dri2_allocate_textures; 24617ec681f3Smrg drawable->flush_frontbuffer = dri2_flush_frontbuffer; 24627ec681f3Smrg drawable->update_tex_buffer = dri2_update_tex_buffer; 24637ec681f3Smrg drawable->flush_swapbuffers = dri2_flush_swapbuffers; 24647ec681f3Smrg 24657ec681f3Smrg return TRUE; 24667ec681f3Smrg} 24677ec681f3Smrg 24687ec681f3Smrg/** 24697ec681f3Smrg * DRI driver virtual function table. 24707ec681f3Smrg * 24717ec681f3Smrg * DRI versions differ in their implementation of init_screen and swap_buffers. 24727ec681f3Smrg */ 24737ec681f3Smrgconst struct __DriverAPIRec galliumdrm_driver_api = { 24747ec681f3Smrg .InitScreen = dri2_init_screen, 24757ec681f3Smrg .DestroyScreen = dri_destroy_screen, 24767ec681f3Smrg .CreateContext = dri_create_context, 24777ec681f3Smrg .DestroyContext = dri_destroy_context, 24787ec681f3Smrg .CreateBuffer = dri2_create_buffer, 24797ec681f3Smrg .DestroyBuffer = dri_destroy_buffer, 24807ec681f3Smrg .MakeCurrent = dri_make_current, 24817ec681f3Smrg .UnbindContext = dri_unbind_context, 24827ec681f3Smrg 24837ec681f3Smrg .AllocateBuffer = dri2_allocate_buffer, 24847ec681f3Smrg .ReleaseBuffer = dri2_release_buffer, 24857ec681f3Smrg}; 24867ec681f3Smrg 24877ec681f3Smrg/** 24887ec681f3Smrg * DRI driver virtual function table. 24897ec681f3Smrg * 24907ec681f3Smrg * KMS/DRM version of the DriverAPI above sporting a different InitScreen 24917ec681f3Smrg * hook. The latter is used to explicitly initialise the kms_swrast driver 24927ec681f3Smrg * rather than selecting the approapriate driver as suggested by the loader. 24937ec681f3Smrg */ 24947ec681f3Smrgconst struct __DriverAPIRec dri_kms_driver_api = { 24957ec681f3Smrg .InitScreen = dri_kms_init_screen, 24967ec681f3Smrg .DestroyScreen = dri_destroy_screen, 24977ec681f3Smrg .CreateContext = dri_create_context, 24987ec681f3Smrg .DestroyContext = dri_destroy_context, 24997ec681f3Smrg .CreateBuffer = dri2_create_buffer, 25007ec681f3Smrg .DestroyBuffer = dri_destroy_buffer, 25017ec681f3Smrg .MakeCurrent = dri_make_current, 25027ec681f3Smrg .UnbindContext = dri_unbind_context, 25037ec681f3Smrg 25047ec681f3Smrg .AllocateBuffer = dri2_allocate_buffer, 25057ec681f3Smrg .ReleaseBuffer = dri2_release_buffer, 25067ec681f3Smrg}; 25077ec681f3Smrg 25087ec681f3Smrg/* This is the table of extensions that the loader will dlsym() for. */ 25097ec681f3Smrgconst __DRIextension *galliumdrm_driver_extensions[] = { 25107ec681f3Smrg &driCoreExtension.base, 25117ec681f3Smrg &driImageDriverExtension.base, 25127ec681f3Smrg &driDRI2Extension.base, 25137ec681f3Smrg &gallium_config_options.base, 25147ec681f3Smrg NULL 25157ec681f3Smrg}; 25167ec681f3Smrg 25177ec681f3Smrg/* vim: set sw=3 ts=8 sts=3 expandtab: */ 2518