Path: blob/21.2-virgl/src/gallium/frontends/dri/dri2.c
4566 views
/*1* Mesa 3-D graphics library2*3* Copyright 2009, VMware, Inc.4* All Rights Reserved.5* Copyright (C) 2010 LunarG Inc.6*7* Permission is hereby granted, free of charge, to any person obtaining a8* copy of this software and associated documentation files (the "Software"),9* to deal in the Software without restriction, including without limitation10* the rights to use, copy, modify, merge, publish, distribute, sublicense,11* and/or sell copies of the Software, and to permit persons to whom the12* Software is furnished to do so, subject to the following conditions:13*14* The above copyright notice and this permission notice shall be included15* in all copies or substantial portions of the Software.16*17* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS18* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,19* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL20* THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR21* OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,22* ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR23* OTHER DEALINGS IN THE SOFTWARE.24*25* Authors:26* Keith Whitwell <[email protected]> Jakob Bornecrantz27* <[email protected]> Chia-I Wu <[email protected]>28*/2930#include <xf86drm.h>31#include "GL/mesa_glinterop.h"32#include "util/disk_cache.h"33#include "util/u_memory.h"34#include "util/u_inlines.h"35#include "util/format/u_format.h"36#include "util/u_debug.h"37#include "frontend/drm_driver.h"38#include "state_tracker/st_cb_bufferobjects.h"39#include "state_tracker/st_cb_fbo.h"40#include "state_tracker/st_cb_texture.h"41#include "state_tracker/st_texture.h"42#include "state_tracker/st_context.h"43#include "pipe-loader/pipe_loader.h"44#include "main/bufferobj.h"45#include "main/texobj.h"4647#include "dri_util.h"4849#include "dri_helpers.h"50#include "dri_drawable.h"51#include "dri_query_renderer.h"5253#include "drm-uapi/drm_fourcc.h"5455struct dri2_buffer56{57__DRIbuffer base;58struct pipe_resource *resource;59};6061static inline struct dri2_buffer *62dri2_buffer(__DRIbuffer * driBufferPriv)63{64return (struct dri2_buffer *) driBufferPriv;65}6667/**68* DRI2 flush extension.69*/70static void71dri2_flush_drawable(__DRIdrawable *dPriv)72{73dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1);74}7576static void77dri2_invalidate_drawable(__DRIdrawable *dPriv)78{79struct dri_drawable *drawable = dri_drawable(dPriv);8081dri2InvalidateDrawable(dPriv);82drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp;83drawable->texture_mask = 0;8485p_atomic_inc(&drawable->base.stamp);86}8788static const __DRI2flushExtension dri2FlushExtension = {89.base = { __DRI2_FLUSH, 4 },9091.flush = dri2_flush_drawable,92.invalidate = dri2_invalidate_drawable,93.flush_with_flags = dri_flush,94};9596/**97* Retrieve __DRIbuffer from the DRI loader.98*/99static __DRIbuffer *100dri2_drawable_get_buffers(struct dri_drawable *drawable,101const enum st_attachment_type *atts,102unsigned *count)103{104__DRIdrawable *dri_drawable = drawable->dPriv;105const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;106boolean with_format;107__DRIbuffer *buffers;108int num_buffers;109unsigned attachments[__DRI_BUFFER_COUNT];110unsigned num_attachments, i;111112assert(loader);113assert(*count <= __DRI_BUFFER_COUNT);114with_format = dri_with_format(drawable->sPriv);115116num_attachments = 0;117118/* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */119if (!with_format)120attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT;121122for (i = 0; i < *count; i++) {123enum pipe_format format;124unsigned bind;125int att, depth;126127dri_drawable_get_format(drawable, atts[i], &format, &bind);128if (format == PIPE_FORMAT_NONE)129continue;130131switch (atts[i]) {132case ST_ATTACHMENT_FRONT_LEFT:133/* already added */134if (!with_format)135continue;136att = __DRI_BUFFER_FRONT_LEFT;137break;138case ST_ATTACHMENT_BACK_LEFT:139att = __DRI_BUFFER_BACK_LEFT;140break;141case ST_ATTACHMENT_FRONT_RIGHT:142att = __DRI_BUFFER_FRONT_RIGHT;143break;144case ST_ATTACHMENT_BACK_RIGHT:145att = __DRI_BUFFER_BACK_RIGHT;146break;147default:148continue;149}150151/*152* In this switch statement we must support all formats that153* may occur as the stvis->color_format.154*/155switch(format) {156case PIPE_FORMAT_R16G16B16A16_FLOAT:157depth = 64;158break;159case PIPE_FORMAT_R16G16B16X16_FLOAT:160depth = 48;161break;162case PIPE_FORMAT_B10G10R10A2_UNORM:163case PIPE_FORMAT_R10G10B10A2_UNORM:164case PIPE_FORMAT_BGRA8888_UNORM:165case PIPE_FORMAT_RGBA8888_UNORM:166depth = 32;167break;168case PIPE_FORMAT_R10G10B10X2_UNORM:169case PIPE_FORMAT_B10G10R10X2_UNORM:170depth = 30;171break;172case PIPE_FORMAT_BGRX8888_UNORM:173case PIPE_FORMAT_RGBX8888_UNORM:174depth = 24;175break;176case PIPE_FORMAT_B5G6R5_UNORM:177depth = 16;178break;179default:180depth = util_format_get_blocksizebits(format);181assert(!"Unexpected format in dri2_drawable_get_buffers()");182}183184attachments[num_attachments++] = att;185if (with_format) {186attachments[num_attachments++] = depth;187}188}189190if (with_format) {191num_attachments /= 2;192buffers = loader->getBuffersWithFormat(dri_drawable,193&dri_drawable->w, &dri_drawable->h,194attachments, num_attachments,195&num_buffers, dri_drawable->loaderPrivate);196}197else {198buffers = loader->getBuffers(dri_drawable,199&dri_drawable->w, &dri_drawable->h,200attachments, num_attachments,201&num_buffers, dri_drawable->loaderPrivate);202}203204if (buffers)205*count = num_buffers;206207return buffers;208}209210static bool211dri_image_drawable_get_buffers(struct dri_drawable *drawable,212struct __DRIimageList *images,213const enum st_attachment_type *statts,214unsigned statts_count)215{216__DRIdrawable *dPriv = drawable->dPriv;217__DRIscreen *sPriv = drawable->sPriv;218unsigned int image_format = __DRI_IMAGE_FORMAT_NONE;219enum pipe_format pf;220uint32_t buffer_mask = 0;221unsigned i, bind;222223for (i = 0; i < statts_count; i++) {224dri_drawable_get_format(drawable, statts[i], &pf, &bind);225if (pf == PIPE_FORMAT_NONE)226continue;227228switch (statts[i]) {229case ST_ATTACHMENT_FRONT_LEFT:230buffer_mask |= __DRI_IMAGE_BUFFER_FRONT;231break;232case ST_ATTACHMENT_BACK_LEFT:233buffer_mask |= __DRI_IMAGE_BUFFER_BACK;234break;235default:236continue;237}238239switch (pf) {240case PIPE_FORMAT_R16G16B16A16_FLOAT:241image_format = __DRI_IMAGE_FORMAT_ABGR16161616F;242break;243case PIPE_FORMAT_R16G16B16X16_FLOAT:244image_format = __DRI_IMAGE_FORMAT_XBGR16161616F;245break;246case PIPE_FORMAT_B5G5R5A1_UNORM:247image_format = __DRI_IMAGE_FORMAT_ARGB1555;248break;249case PIPE_FORMAT_B5G6R5_UNORM:250image_format = __DRI_IMAGE_FORMAT_RGB565;251break;252case PIPE_FORMAT_BGRX8888_UNORM:253image_format = __DRI_IMAGE_FORMAT_XRGB8888;254break;255case PIPE_FORMAT_BGRA8888_UNORM:256image_format = __DRI_IMAGE_FORMAT_ARGB8888;257break;258case PIPE_FORMAT_RGBX8888_UNORM:259image_format = __DRI_IMAGE_FORMAT_XBGR8888;260break;261case PIPE_FORMAT_RGBA8888_UNORM:262image_format = __DRI_IMAGE_FORMAT_ABGR8888;263break;264case PIPE_FORMAT_B10G10R10X2_UNORM:265image_format = __DRI_IMAGE_FORMAT_XRGB2101010;266break;267case PIPE_FORMAT_B10G10R10A2_UNORM:268image_format = __DRI_IMAGE_FORMAT_ARGB2101010;269break;270case PIPE_FORMAT_R10G10B10X2_UNORM:271image_format = __DRI_IMAGE_FORMAT_XBGR2101010;272break;273case PIPE_FORMAT_R10G10B10A2_UNORM:274image_format = __DRI_IMAGE_FORMAT_ABGR2101010;275break;276default:277image_format = __DRI_IMAGE_FORMAT_NONE;278break;279}280}281282return (*sPriv->image.loader->getBuffers) (dPriv, image_format,283(uint32_t *) &drawable->base.stamp,284dPriv->loaderPrivate, buffer_mask,285images);286}287288static __DRIbuffer *289dri2_allocate_buffer(__DRIscreen *sPriv,290unsigned attachment, unsigned format,291int width, int height)292{293struct dri_screen *screen = dri_screen(sPriv);294struct dri2_buffer *buffer;295struct pipe_resource templ;296enum pipe_format pf;297unsigned bind = 0;298struct winsys_handle whandle;299300switch (attachment) {301case __DRI_BUFFER_FRONT_LEFT:302case __DRI_BUFFER_FAKE_FRONT_LEFT:303bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;304break;305case __DRI_BUFFER_BACK_LEFT:306bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW;307break;308case __DRI_BUFFER_DEPTH:309case __DRI_BUFFER_DEPTH_STENCIL:310case __DRI_BUFFER_STENCIL:311bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */312break;313}314315/* because we get the handle and stride */316bind |= PIPE_BIND_SHARED;317318switch (format) {319case 64:320pf = PIPE_FORMAT_R16G16B16A16_FLOAT;321break;322case 48:323pf = PIPE_FORMAT_R16G16B16X16_FLOAT;324break;325case 32:326pf = PIPE_FORMAT_BGRA8888_UNORM;327break;328case 30:329pf = PIPE_FORMAT_B10G10R10X2_UNORM;330break;331case 24:332pf = PIPE_FORMAT_BGRX8888_UNORM;333break;334case 16:335pf = PIPE_FORMAT_Z16_UNORM;336break;337default:338return NULL;339}340341buffer = CALLOC_STRUCT(dri2_buffer);342if (!buffer)343return NULL;344345memset(&templ, 0, sizeof(templ));346templ.bind = bind;347templ.format = pf;348templ.target = PIPE_TEXTURE_2D;349templ.last_level = 0;350templ.width0 = width;351templ.height0 = height;352templ.depth0 = 1;353templ.array_size = 1;354355buffer->resource =356screen->base.screen->resource_create(screen->base.screen, &templ);357if (!buffer->resource) {358FREE(buffer);359return NULL;360}361362memset(&whandle, 0, sizeof(whandle));363if (screen->can_share_buffer)364whandle.type = WINSYS_HANDLE_TYPE_SHARED;365else366whandle.type = WINSYS_HANDLE_TYPE_KMS;367368screen->base.screen->resource_get_handle(screen->base.screen, NULL,369buffer->resource, &whandle,370PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);371372buffer->base.attachment = attachment;373buffer->base.name = whandle.handle;374buffer->base.cpp = util_format_get_blocksize(pf);375buffer->base.pitch = whandle.stride;376377return &buffer->base;378}379380static void381dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv)382{383struct dri2_buffer *buffer = dri2_buffer(bPriv);384385pipe_resource_reference(&buffer->resource, NULL);386FREE(buffer);387}388389/*390* Backend functions for st_framebuffer interface.391*/392393static void394dri2_allocate_textures(struct dri_context *ctx,395struct dri_drawable *drawable,396const enum st_attachment_type *statts,397unsigned statts_count)398{399__DRIscreen *sPriv = drawable->sPriv;400__DRIdrawable *dri_drawable = drawable->dPriv;401struct dri_screen *screen = dri_screen(sPriv);402struct pipe_resource templ;403boolean alloc_depthstencil = FALSE;404unsigned i, j, bind;405const __DRIimageLoaderExtension *image = sPriv->image.loader;406/* Image specific variables */407struct __DRIimageList images;408/* Dri2 specific variables */409__DRIbuffer *buffers = NULL;410struct winsys_handle whandle;411unsigned num_buffers = statts_count;412413assert(num_buffers <= __DRI_BUFFER_COUNT);414415/* First get the buffers from the loader */416if (image) {417if (!dri_image_drawable_get_buffers(drawable, &images,418statts, statts_count))419return;420}421else {422buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers);423if (!buffers || (drawable->old_num == num_buffers &&424drawable->old_w == dri_drawable->w &&425drawable->old_h == dri_drawable->h &&426memcmp(drawable->old, buffers,427sizeof(__DRIbuffer) * num_buffers) == 0))428return;429}430431/* Second clean useless resources*/432433/* See if we need a depth-stencil buffer. */434for (i = 0; i < statts_count; i++) {435if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) {436alloc_depthstencil = TRUE;437break;438}439}440441/* Delete the resources we won't need. */442for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {443/* Don't delete the depth-stencil buffer, we can reuse it. */444if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil)445continue;446447/* Flush the texture before unreferencing, so that other clients can448* see what the driver has rendered.449*/450if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) {451struct pipe_context *pipe = ctx->st->pipe;452pipe->flush_resource(pipe, drawable->textures[i]);453}454455pipe_resource_reference(&drawable->textures[i], NULL);456}457458if (drawable->stvis.samples > 1) {459for (i = 0; i < ST_ATTACHMENT_COUNT; i++) {460boolean del = TRUE;461462/* Don't delete MSAA resources for the attachments which are enabled,463* we can reuse them. */464for (j = 0; j < statts_count; j++) {465if (i == statts[j]) {466del = FALSE;467break;468}469}470471if (del) {472pipe_resource_reference(&drawable->msaa_textures[i], NULL);473}474}475}476477/* Third use the buffers retrieved to fill the drawable info */478479memset(&templ, 0, sizeof(templ));480templ.target = screen->target;481templ.last_level = 0;482templ.depth0 = 1;483templ.array_size = 1;484485if (image) {486if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) {487struct pipe_resource **buf =488&drawable->textures[ST_ATTACHMENT_FRONT_LEFT];489struct pipe_resource *texture = images.front->texture;490491dri_drawable->w = texture->width0;492dri_drawable->h = texture->height0;493494pipe_resource_reference(buf, texture);495}496497if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) {498struct pipe_resource **buf =499&drawable->textures[ST_ATTACHMENT_BACK_LEFT];500struct pipe_resource *texture = images.back->texture;501502dri_drawable->w = texture->width0;503dri_drawable->h = texture->height0;504505pipe_resource_reference(buf, texture);506}507508if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) {509struct pipe_resource **buf =510&drawable->textures[ST_ATTACHMENT_BACK_LEFT];511struct pipe_resource *texture = images.back->texture;512513dri_drawable->w = texture->width0;514dri_drawable->h = texture->height0;515516pipe_resource_reference(buf, texture);517518ctx->is_shared_buffer_bound = true;519} else {520ctx->is_shared_buffer_bound = false;521}522523/* Note: if there is both a back and a front buffer,524* then they have the same size.525*/526templ.width0 = dri_drawable->w;527templ.height0 = dri_drawable->h;528}529else {530memset(&whandle, 0, sizeof(whandle));531532/* Process DRI-provided buffers and get pipe_resources. */533for (i = 0; i < num_buffers; i++) {534__DRIbuffer *buf = &buffers[i];535enum st_attachment_type statt;536enum pipe_format format;537538switch (buf->attachment) {539case __DRI_BUFFER_FRONT_LEFT:540if (!screen->auto_fake_front) {541continue; /* invalid attachment */542}543FALLTHROUGH;544case __DRI_BUFFER_FAKE_FRONT_LEFT:545statt = ST_ATTACHMENT_FRONT_LEFT;546break;547case __DRI_BUFFER_BACK_LEFT:548statt = ST_ATTACHMENT_BACK_LEFT;549break;550default:551continue; /* invalid attachment */552}553554dri_drawable_get_format(drawable, statt, &format, &bind);555if (format == PIPE_FORMAT_NONE)556continue;557558/* dri2_drawable_get_buffers has already filled dri_drawable->w559* and dri_drawable->h */560templ.width0 = dri_drawable->w;561templ.height0 = dri_drawable->h;562templ.format = format;563templ.bind = bind;564whandle.handle = buf->name;565whandle.stride = buf->pitch;566whandle.offset = 0;567whandle.format = format;568whandle.modifier = DRM_FORMAT_MOD_INVALID;569if (screen->can_share_buffer)570whandle.type = WINSYS_HANDLE_TYPE_SHARED;571else572whandle.type = WINSYS_HANDLE_TYPE_KMS;573drawable->textures[statt] =574screen->base.screen->resource_from_handle(screen->base.screen,575&templ, &whandle,576PIPE_HANDLE_USAGE_EXPLICIT_FLUSH);577assert(drawable->textures[statt]);578}579}580581/* Allocate private MSAA colorbuffers. */582if (drawable->stvis.samples > 1) {583for (i = 0; i < statts_count; i++) {584enum st_attachment_type statt = statts[i];585586if (statt == ST_ATTACHMENT_DEPTH_STENCIL)587continue;588589if (drawable->textures[statt]) {590templ.format = drawable->textures[statt]->format;591templ.bind = drawable->textures[statt]->bind &592~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED);593templ.nr_samples = drawable->stvis.samples;594templ.nr_storage_samples = drawable->stvis.samples;595596/* Try to reuse the resource.597* (the other resource parameters should be constant)598*/599if (!drawable->msaa_textures[statt] ||600drawable->msaa_textures[statt]->width0 != templ.width0 ||601drawable->msaa_textures[statt]->height0 != templ.height0) {602/* Allocate a new one. */603pipe_resource_reference(&drawable->msaa_textures[statt], NULL);604605drawable->msaa_textures[statt] =606screen->base.screen->resource_create(screen->base.screen,607&templ);608assert(drawable->msaa_textures[statt]);609610/* If there are any MSAA resources, we should initialize them611* such that they contain the same data as the single-sample612* resources we just got from the X server.613*614* The reason for this is that the gallium frontend (and615* therefore the app) can access the MSAA resources only.616* The single-sample resources are not exposed617* to the gallium frontend.618*619*/620dri_pipe_blit(ctx->st->pipe,621drawable->msaa_textures[statt],622drawable->textures[statt]);623}624}625else {626pipe_resource_reference(&drawable->msaa_textures[statt], NULL);627}628}629}630631/* Allocate a private depth-stencil buffer. */632if (alloc_depthstencil) {633enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL;634struct pipe_resource **zsbuf;635enum pipe_format format;636unsigned bind;637638dri_drawable_get_format(drawable, statt, &format, &bind);639640if (format) {641templ.format = format;642templ.bind = bind & ~PIPE_BIND_SHARED;643644if (drawable->stvis.samples > 1) {645templ.nr_samples = drawable->stvis.samples;646templ.nr_storage_samples = drawable->stvis.samples;647zsbuf = &drawable->msaa_textures[statt];648}649else {650templ.nr_samples = 0;651templ.nr_storage_samples = 0;652zsbuf = &drawable->textures[statt];653}654655/* Try to reuse the resource.656* (the other resource parameters should be constant)657*/658if (!*zsbuf ||659(*zsbuf)->width0 != templ.width0 ||660(*zsbuf)->height0 != templ.height0) {661/* Allocate a new one. */662pipe_resource_reference(zsbuf, NULL);663*zsbuf = screen->base.screen->resource_create(screen->base.screen,664&templ);665assert(*zsbuf);666}667}668else {669pipe_resource_reference(&drawable->msaa_textures[statt], NULL);670pipe_resource_reference(&drawable->textures[statt], NULL);671}672}673674/* For DRI2, we may get the same buffers again from the server.675* To prevent useless imports of gem names, drawable->old* is used676* to bypass the import if we get the same buffers. This doesn't apply677* to DRI3/Wayland, users of image.loader, since the buffer is managed678* by the client (no import), and the back buffer is going to change679* at every redraw.680*/681if (!image) {682drawable->old_num = num_buffers;683drawable->old_w = dri_drawable->w;684drawable->old_h = dri_drawable->h;685memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers);686}687}688689static bool690dri2_flush_frontbuffer(struct dri_context *ctx,691struct dri_drawable *drawable,692enum st_attachment_type statt)693{694__DRIdrawable *dri_drawable = drawable->dPriv;695const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;696const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader;697const __DRImutableRenderBufferLoaderExtension *shared_buffer_loader =698drawable->sPriv->mutableRenderBuffer.loader;699struct pipe_context *pipe = ctx->st->pipe;700struct pipe_fence_handle *fence = NULL;701int fence_fd = -1;702703/* We need to flush for front buffer rendering when either we're using the704* front buffer at the GL API level, or when EGL_KHR_mutable_render_buffer705* has redirected GL_BACK to the front buffer.706*/707if (statt != ST_ATTACHMENT_FRONT_LEFT &&708(!ctx->is_shared_buffer_bound || statt != ST_ATTACHMENT_BACK_LEFT))709return false;710711if (drawable->stvis.samples > 1) {712/* Resolve the buffer used for front rendering. */713dri_pipe_blit(ctx->st->pipe, drawable->textures[statt],714drawable->msaa_textures[statt]);715}716717if (drawable->textures[statt]) {718pipe->flush_resource(pipe, drawable->textures[statt]);719}720721if (ctx->is_shared_buffer_bound) {722/* is_shared_buffer_bound should only be true with image extension: */723assert(image);724pipe->flush(pipe, &fence, PIPE_FLUSH_FENCE_FD);725} else {726pipe->flush(pipe, NULL, 0);727}728729if (image) {730image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);731if (ctx->is_shared_buffer_bound) {732if (fence)733fence_fd = pipe->screen->fence_get_fd(pipe->screen, fence);734735shared_buffer_loader->displaySharedBuffer(dri_drawable, fence_fd,736dri_drawable->loaderPrivate);737738pipe->screen->fence_reference(pipe->screen, &fence, NULL);739}740}741else if (loader->flushFrontBuffer) {742loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate);743}744745return true;746}747748/**749* The struct dri_drawable flush_swapbuffers callback750*/751static void752dri2_flush_swapbuffers(struct dri_context *ctx,753struct dri_drawable *drawable)754{755__DRIdrawable *dri_drawable = drawable->dPriv;756const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader;757758if (image && image->base.version >= 3 && image->flushSwapBuffers) {759image->flushSwapBuffers(dri_drawable, dri_drawable->loaderPrivate);760}761}762763static void764dri2_update_tex_buffer(struct dri_drawable *drawable,765struct dri_context *ctx,766struct pipe_resource *res)767{768/* no-op */769}770771static const struct dri2_format_mapping r8_g8b8_mapping = {772DRM_FORMAT_NV12,773__DRI_IMAGE_FORMAT_NONE,774__DRI_IMAGE_COMPONENTS_Y_UV,775PIPE_FORMAT_R8_G8B8_420_UNORM,7762,777{ { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 },778{ 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } }779};780781static const struct dri2_format_mapping r8g8_r8b8_mapping = {782DRM_FORMAT_YUYV,783__DRI_IMAGE_FORMAT_NONE,784__DRI_IMAGE_COMPONENTS_Y_XUXV,785PIPE_FORMAT_R8G8_R8B8_UNORM, 2,786{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },787{ 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } }788};789790static const struct dri2_format_mapping g8r8_b8r8_mapping = {791DRM_FORMAT_UYVY,792__DRI_IMAGE_FORMAT_NONE,793__DRI_IMAGE_COMPONENTS_Y_XUXV,794PIPE_FORMAT_G8R8_B8R8_UNORM, 2,795{ { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 },796{ 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } }797};798799static __DRIimage *800dri2_create_image_from_winsys(__DRIscreen *_screen,801int width, int height, const struct dri2_format_mapping *map,802int num_handles, struct winsys_handle *whandle,803bool is_protected_content,804void *loaderPrivate)805{806struct dri_screen *screen = dri_screen(_screen);807struct pipe_screen *pscreen = screen->base.screen;808__DRIimage *img;809struct pipe_resource templ;810unsigned tex_usage = 0;811int i;812bool use_lowered = false;813const unsigned format_planes = util_format_get_num_planes(map->pipe_format);814815if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,816PIPE_BIND_RENDER_TARGET))817tex_usage |= PIPE_BIND_RENDER_TARGET;818if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0,819PIPE_BIND_SAMPLER_VIEW))820tex_usage |= PIPE_BIND_SAMPLER_VIEW;821822/* For NV12, see if we have support for sampling r8_b8g8 */823if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV12 &&824pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8B8_420_UNORM,825screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {826map = &r8_g8b8_mapping;827tex_usage |= PIPE_BIND_SAMPLER_VIEW;828}829830/* If the hardware supports R8G8_R8B8 style subsampled RGB formats, these831* can be used for YUYV and UYVY formats.832*/833if (!tex_usage && map->pipe_format == PIPE_FORMAT_YUYV &&834pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8G8_R8B8_UNORM,835screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {836map = &r8g8_r8b8_mapping;837tex_usage |= PIPE_BIND_SAMPLER_VIEW;838}839840if (!tex_usage && map->pipe_format == PIPE_FORMAT_UYVY &&841pscreen->is_format_supported(pscreen, PIPE_FORMAT_G8R8_B8R8_UNORM,842screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) {843map = &g8r8_b8r8_mapping;844tex_usage |= PIPE_BIND_SAMPLER_VIEW;845}846847if (!tex_usage && util_format_is_yuv(map->pipe_format)) {848/* YUV format sampling can be emulated by the GL gallium frontend by849* using multiple samplers of varying formats.850* If no tex_usage is set and we detect a YUV format,851* test for support of all planes' sampler formats and852* add sampler view usage.853*/854use_lowered = true;855if (dri2_yuv_dma_buf_supported(screen, map))856tex_usage |= PIPE_BIND_SAMPLER_VIEW;857}858859if (!tex_usage)860return NULL;861862if (is_protected_content)863tex_usage |= PIPE_BIND_PROTECTED;864865img = CALLOC_STRUCT(__DRIimageRec);866if (!img)867return NULL;868869memset(&templ, 0, sizeof(templ));870templ.bind = tex_usage;871templ.target = screen->target;872templ.last_level = 0;873templ.depth0 = 1;874templ.array_size = 1;875876for (i = num_handles - 1; i >= format_planes; i--) {877struct pipe_resource *tex;878879templ.next = img->texture;880881tex = pscreen->resource_from_handle(pscreen, &templ, &whandle[i],882PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);883if (!tex) {884pipe_resource_reference(&img->texture, NULL);885FREE(img);886return NULL;887}888889img->texture = tex;890}891892for (i = (use_lowered ? map->nplanes : format_planes) - 1; i >= 0; i--) {893struct pipe_resource *tex;894895templ.next = img->texture;896templ.width0 = width >> map->planes[i].width_shift;897templ.height0 = height >> map->planes[i].height_shift;898if (use_lowered)899templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format);900else901templ.format = map->pipe_format;902assert(templ.format != PIPE_FORMAT_NONE);903904tex = pscreen->resource_from_handle(pscreen,905&templ, &whandle[use_lowered ? map->planes[i].buffer_index : i],906PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE);907if (!tex) {908pipe_resource_reference(&img->texture, NULL);909FREE(img);910return NULL;911}912913/* Reject image creation if there's an inconsistency between914* content protection status of tex and img.915*/916const struct driOptionCache *optionCache = &screen->dev->option_cache;917if (!driQueryOptionb(optionCache, "disable_protected_content_check") &&918(bool)(tex->bind & PIPE_BIND_PROTECTED) != is_protected_content) {919pipe_resource_reference(&img->texture, NULL);920pipe_resource_reference(&tex, NULL);921FREE(img);922return NULL;923}924925img->texture = tex;926}927928img->level = 0;929img->layer = 0;930img->use = 0;931img->loader_private = loaderPrivate;932img->sPriv = _screen;933934return img;935}936937static __DRIimage *938dri2_create_image_from_name(__DRIscreen *_screen,939int width, int height, int format,940int name, int pitch, void *loaderPrivate)941{942const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);943struct winsys_handle whandle;944__DRIimage *img;945946if (!map)947return NULL;948949memset(&whandle, 0, sizeof(whandle));950whandle.type = WINSYS_HANDLE_TYPE_SHARED;951whandle.handle = name;952whandle.format = map->pipe_format;953whandle.modifier = DRM_FORMAT_MOD_INVALID;954955whandle.stride = pitch * util_format_get_blocksize(map->pipe_format);956957img = dri2_create_image_from_winsys(_screen, width, height, map,9581, &whandle, false, loaderPrivate);959960if (!img)961return NULL;962963img->dri_components = map->dri_components;964img->dri_fourcc = map->dri_fourcc;965img->dri_format = map->dri_format;966967return img;968}969970static unsigned971dri2_get_modifier_num_planes(__DRIscreen *_screen,972uint64_t modifier, int fourcc)973{974struct pipe_screen *pscreen = dri_screen(_screen)->base.screen;975const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);976977if (!map)978return 0;979980switch (modifier) {981case DRM_FORMAT_MOD_LINEAR:982/* DRM_FORMAT_MOD_NONE is the same as LINEAR */983case DRM_FORMAT_MOD_INVALID:984return util_format_get_num_planes(map->pipe_format);985default:986if (!pscreen->is_dmabuf_modifier_supported ||987!pscreen->is_dmabuf_modifier_supported(pscreen, modifier,988map->pipe_format, NULL)) {989return 0;990}991992if (pscreen->get_dmabuf_modifier_planes) {993return pscreen->get_dmabuf_modifier_planes(pscreen, modifier,994map->pipe_format);995}996997return map->nplanes;998}999}10001001static __DRIimage *1002dri2_create_image_from_fd(__DRIscreen *_screen,1003int width, int height, int fourcc,1004uint64_t modifier, int *fds, int num_fds,1005int *strides, int *offsets, bool protected_content,1006unsigned *error, void *loaderPrivate)1007{1008struct winsys_handle whandles[4];1009const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);1010__DRIimage *img = NULL;1011unsigned err = __DRI_IMAGE_ERROR_SUCCESS;1012int i;1013const int expected_num_fds = dri2_get_modifier_num_planes(_screen, modifier, fourcc);10141015if (!map || expected_num_fds == 0) {1016err = __DRI_IMAGE_ERROR_BAD_MATCH;1017goto exit;1018}10191020if (num_fds != expected_num_fds) {1021err = __DRI_IMAGE_ERROR_BAD_MATCH;1022goto exit;1023}10241025memset(whandles, 0, sizeof(whandles));10261027for (i = 0; i < num_fds; i++) {1028if (fds[i] < 0) {1029err = __DRI_IMAGE_ERROR_BAD_ALLOC;1030goto exit;1031}10321033whandles[i].type = WINSYS_HANDLE_TYPE_FD;1034whandles[i].handle = (unsigned)fds[i];1035whandles[i].stride = (unsigned)strides[i];1036whandles[i].offset = (unsigned)offsets[i];1037whandles[i].format = map->pipe_format;1038whandles[i].modifier = modifier;1039whandles[i].plane = i;1040}10411042img = dri2_create_image_from_winsys(_screen, width, height, map,1043num_fds, whandles, protected_content,1044loaderPrivate);1045if(img == NULL) {1046err = __DRI_IMAGE_ERROR_BAD_ALLOC;1047goto exit;1048}10491050img->dri_components = map->dri_components;1051img->dri_fourcc = fourcc;1052img->dri_format = map->dri_format;1053img->imported_dmabuf = TRUE;10541055exit:1056if (error)1057*error = err;10581059return img;1060}10611062static __DRIimage *1063dri2_create_image_common(__DRIscreen *_screen,1064int width, int height,1065int format, unsigned int use,1066const uint64_t *modifiers,1067const unsigned count,1068void *loaderPrivate)1069{1070const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);1071struct dri_screen *screen = dri_screen(_screen);1072struct pipe_screen *pscreen = screen->base.screen;1073__DRIimage *img;1074struct pipe_resource templ;1075unsigned tex_usage = 0;10761077if (!map)1078return NULL;10791080if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target,10810, 0, PIPE_BIND_RENDER_TARGET))1082tex_usage |= PIPE_BIND_RENDER_TARGET;1083if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target,10840, 0, PIPE_BIND_SAMPLER_VIEW))1085tex_usage |= PIPE_BIND_SAMPLER_VIEW;10861087if (!tex_usage)1088return NULL;10891090if (use & __DRI_IMAGE_USE_SCANOUT)1091tex_usage |= PIPE_BIND_SCANOUT;1092if (use & __DRI_IMAGE_USE_SHARE)1093tex_usage |= PIPE_BIND_SHARED;1094if (use & __DRI_IMAGE_USE_LINEAR)1095tex_usage |= PIPE_BIND_LINEAR;1096if (use & __DRI_IMAGE_USE_CURSOR) {1097if (width != 64 || height != 64)1098return NULL;1099tex_usage |= PIPE_BIND_CURSOR;1100}1101if (use & __DRI_IMAGE_USE_PROTECTED)1102tex_usage |= PIPE_BIND_PROTECTED;11031104img = CALLOC_STRUCT(__DRIimageRec);1105if (!img)1106return NULL;11071108memset(&templ, 0, sizeof(templ));1109templ.bind = tex_usage;1110templ.format = map->pipe_format;1111templ.target = PIPE_TEXTURE_2D;1112templ.last_level = 0;1113templ.width0 = width;1114templ.height0 = height;1115templ.depth0 = 1;1116templ.array_size = 1;11171118if (modifiers)1119img->texture =1120screen->base.screen1121->resource_create_with_modifiers(screen->base.screen,1122&templ,1123modifiers,1124count);1125else1126img->texture =1127screen->base.screen->resource_create(screen->base.screen, &templ);1128if (!img->texture) {1129FREE(img);1130return NULL;1131}11321133img->level = 0;1134img->layer = 0;1135img->dri_format = format;1136img->dri_fourcc = map->dri_fourcc;1137img->dri_components = 0;1138img->use = use;11391140img->loader_private = loaderPrivate;1141img->sPriv = _screen;1142return img;1143}11441145static __DRIimage *1146dri2_create_image(__DRIscreen *_screen,1147int width, int height, int format,1148unsigned int use, void *loaderPrivate)1149{1150return dri2_create_image_common(_screen, width, height, format, use,1151NULL /* modifiers */, 0 /* count */,1152loaderPrivate);1153}11541155static __DRIimage *1156dri2_create_image_with_modifiers(__DRIscreen *dri_screen,1157int width, int height, int format,1158const uint64_t *modifiers,1159const unsigned count,1160void *loaderPrivate)1161{1162return dri2_create_image_common(dri_screen, width, height, format,1163__DRI_IMAGE_USE_SHARE, modifiers, count,1164loaderPrivate);1165}11661167static __DRIimage *1168dri2_create_image_with_modifiers2(__DRIscreen *dri_screen,1169int width, int height, int format,1170const uint64_t *modifiers,1171const unsigned count, unsigned int use,1172void *loaderPrivate)1173{1174return dri2_create_image_common(dri_screen, width, height, format, use,1175modifiers, count, loaderPrivate);1176}11771178static bool1179dri2_query_image_common(__DRIimage *image, int attrib, int *value)1180{1181switch (attrib) {1182case __DRI_IMAGE_ATTRIB_FORMAT:1183*value = image->dri_format;1184return true;1185case __DRI_IMAGE_ATTRIB_WIDTH:1186*value = image->texture->width0;1187return true;1188case __DRI_IMAGE_ATTRIB_HEIGHT:1189*value = image->texture->height0;1190return true;1191case __DRI_IMAGE_ATTRIB_COMPONENTS:1192if (image->dri_components == 0)1193return false;1194*value = image->dri_components;1195return true;1196case __DRI_IMAGE_ATTRIB_FOURCC:1197if (image->dri_fourcc) {1198*value = image->dri_fourcc;1199} else {1200const struct dri2_format_mapping *map;12011202map = dri2_get_mapping_by_format(image->dri_format);1203if (!map)1204return false;12051206*value = map->dri_fourcc;1207}1208return true;1209default:1210return false;1211}1212}12131214static bool1215dri2_query_image_by_resource_handle(__DRIimage *image, int attrib, int *value)1216{1217struct pipe_screen *pscreen = image->texture->screen;1218struct winsys_handle whandle;1219struct pipe_resource *tex;1220unsigned usage;1221memset(&whandle, 0, sizeof(whandle));1222whandle.plane = image->plane;1223int i;12241225switch (attrib) {1226case __DRI_IMAGE_ATTRIB_STRIDE:1227case __DRI_IMAGE_ATTRIB_OFFSET:1228case __DRI_IMAGE_ATTRIB_HANDLE:1229whandle.type = WINSYS_HANDLE_TYPE_KMS;1230break;1231case __DRI_IMAGE_ATTRIB_NAME:1232whandle.type = WINSYS_HANDLE_TYPE_SHARED;1233break;1234case __DRI_IMAGE_ATTRIB_FD:1235whandle.type = WINSYS_HANDLE_TYPE_FD;1236break;1237case __DRI_IMAGE_ATTRIB_NUM_PLANES:1238for (i = 0, tex = image->texture; tex; tex = tex->next)1239i++;1240*value = i;1241return true;1242case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:1243case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:1244whandle.type = WINSYS_HANDLE_TYPE_KMS;1245whandle.modifier = DRM_FORMAT_MOD_INVALID;1246break;1247default:1248return false;1249}12501251usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;12521253if (image->use & __DRI_IMAGE_USE_BACKBUFFER)1254usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;12551256if (!pscreen->resource_get_handle(pscreen, NULL, image->texture,1257&whandle, usage))1258return false;12591260switch (attrib) {1261case __DRI_IMAGE_ATTRIB_STRIDE:1262*value = whandle.stride;1263return true;1264case __DRI_IMAGE_ATTRIB_OFFSET:1265*value = whandle.offset;1266return true;1267case __DRI_IMAGE_ATTRIB_HANDLE:1268case __DRI_IMAGE_ATTRIB_NAME:1269case __DRI_IMAGE_ATTRIB_FD:1270*value = whandle.handle;1271return true;1272case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:1273if (whandle.modifier == DRM_FORMAT_MOD_INVALID)1274return false;1275*value = (whandle.modifier >> 32) & 0xffffffff;1276return true;1277case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:1278if (whandle.modifier == DRM_FORMAT_MOD_INVALID)1279return false;1280*value = whandle.modifier & 0xffffffff;1281return true;1282default:1283return false;1284}1285}12861287static bool1288dri2_resource_get_param(__DRIimage *image, enum pipe_resource_param param,1289unsigned handle_usage, uint64_t *value)1290{1291struct pipe_screen *pscreen = image->texture->screen;1292if (!pscreen->resource_get_param)1293return false;12941295if (image->use & __DRI_IMAGE_USE_BACKBUFFER)1296handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH;12971298return pscreen->resource_get_param(pscreen, NULL, image->texture,1299image->plane, 0, 0, param, handle_usage,1300value);1301}13021303static bool1304dri2_query_image_by_resource_param(__DRIimage *image, int attrib, int *value)1305{1306enum pipe_resource_param param;1307uint64_t res_param;1308unsigned handle_usage;13091310if (!image->texture->screen->resource_get_param)1311return false;13121313switch (attrib) {1314case __DRI_IMAGE_ATTRIB_STRIDE:1315param = PIPE_RESOURCE_PARAM_STRIDE;1316break;1317case __DRI_IMAGE_ATTRIB_OFFSET:1318param = PIPE_RESOURCE_PARAM_OFFSET;1319break;1320case __DRI_IMAGE_ATTRIB_NUM_PLANES:1321param = PIPE_RESOURCE_PARAM_NPLANES;1322break;1323case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:1324case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:1325param = PIPE_RESOURCE_PARAM_MODIFIER;1326break;1327case __DRI_IMAGE_ATTRIB_HANDLE:1328param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS;1329break;1330case __DRI_IMAGE_ATTRIB_NAME:1331param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED;1332break;1333case __DRI_IMAGE_ATTRIB_FD:1334param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD;1335break;1336default:1337return false;1338}13391340handle_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE;13411342if (!dri2_resource_get_param(image, param, handle_usage, &res_param))1343return false;13441345switch (attrib) {1346case __DRI_IMAGE_ATTRIB_STRIDE:1347case __DRI_IMAGE_ATTRIB_OFFSET:1348case __DRI_IMAGE_ATTRIB_NUM_PLANES:1349if (res_param > INT_MAX)1350return false;1351*value = (int)res_param;1352return true;1353case __DRI_IMAGE_ATTRIB_HANDLE:1354case __DRI_IMAGE_ATTRIB_NAME:1355case __DRI_IMAGE_ATTRIB_FD:1356if (res_param > UINT_MAX)1357return false;1358*value = (int)res_param;1359return true;1360case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER:1361if (res_param == DRM_FORMAT_MOD_INVALID)1362return false;1363*value = (res_param >> 32) & 0xffffffff;1364return true;1365case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER:1366if (res_param == DRM_FORMAT_MOD_INVALID)1367return false;1368*value = res_param & 0xffffffff;1369return true;1370default:1371return false;1372}1373}13741375static GLboolean1376dri2_query_image(__DRIimage *image, int attrib, int *value)1377{1378if (dri2_query_image_common(image, attrib, value))1379return GL_TRUE;1380else if (dri2_query_image_by_resource_param(image, attrib, value))1381return GL_TRUE;1382else if (dri2_query_image_by_resource_handle(image, attrib, value))1383return GL_TRUE;1384else1385return GL_FALSE;1386}13871388static __DRIimage *1389dri2_dup_image(__DRIimage *image, void *loaderPrivate)1390{1391__DRIimage *img;13921393img = CALLOC_STRUCT(__DRIimageRec);1394if (!img)1395return NULL;13961397img->texture = NULL;1398pipe_resource_reference(&img->texture, image->texture);1399img->level = image->level;1400img->layer = image->layer;1401img->dri_format = image->dri_format;1402/* This should be 0 for sub images, but dup is also used for base images. */1403img->dri_components = image->dri_components;1404img->use = image->use;1405img->loader_private = loaderPrivate;1406img->sPriv = image->sPriv;14071408return img;1409}14101411static GLboolean1412dri2_validate_usage(__DRIimage *image, unsigned int use)1413{1414if (!image || !image->texture)1415return false;14161417struct pipe_screen *screen = image->texture->screen;1418if (!screen->check_resource_capability)1419return true;14201421/* We don't want to check these:1422* __DRI_IMAGE_USE_SHARE (all images are shareable)1423* __DRI_IMAGE_USE_BACKBUFFER (all images support this)1424*/1425unsigned bind = 0;1426if (use & __DRI_IMAGE_USE_SCANOUT)1427bind |= PIPE_BIND_SCANOUT;1428if (use & __DRI_IMAGE_USE_LINEAR)1429bind |= PIPE_BIND_LINEAR;1430if (use & __DRI_IMAGE_USE_CURSOR)1431bind |= PIPE_BIND_CURSOR;14321433if (!bind)1434return true;14351436return screen->check_resource_capability(screen, image->texture, bind);1437}14381439static __DRIimage *1440dri2_from_names(__DRIscreen *screen, int width, int height, int format,1441int *names, int num_names, int *strides, int *offsets,1442void *loaderPrivate)1443{1444const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format);1445__DRIimage *img;1446struct winsys_handle whandle;14471448if (!map)1449return NULL;14501451if (num_names != 1)1452return NULL;14531454memset(&whandle, 0, sizeof(whandle));1455whandle.type = WINSYS_HANDLE_TYPE_SHARED;1456whandle.handle = names[0];1457whandle.stride = strides[0];1458whandle.offset = offsets[0];1459whandle.format = map->pipe_format;1460whandle.modifier = DRM_FORMAT_MOD_INVALID;14611462img = dri2_create_image_from_winsys(screen, width, height, map,14631, &whandle, false, loaderPrivate);1464if (img == NULL)1465return NULL;14661467img->dri_components = map->dri_components;1468img->dri_fourcc = map->dri_fourcc;1469img->dri_format = map->pipe_format;14701471return img;1472}14731474static __DRIimage *1475dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate)1476{1477__DRIimage *img;14781479if (plane < 0) {1480return NULL;1481} else if (plane > 0) {1482uint64_t planes;1483if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_NPLANES, 0,1484&planes) ||1485plane >= planes) {1486return NULL;1487}1488}14891490if (image->dri_components == 0) {1491uint64_t modifier;1492if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_MODIFIER, 0,1493&modifier) ||1494modifier == DRM_FORMAT_MOD_INVALID) {1495return NULL;1496}1497}14981499img = dri2_dup_image(image, loaderPrivate);1500if (img == NULL)1501return NULL;15021503if (img->texture->screen->resource_changed)1504img->texture->screen->resource_changed(img->texture->screen,1505img->texture);15061507/* set this to 0 for sub images. */1508img->dri_components = 0;1509img->plane = plane;1510return img;1511}15121513static __DRIimage *1514dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc,1515int *fds, int num_fds, int *strides, int *offsets,1516void *loaderPrivate)1517{1518return dri2_create_image_from_fd(screen, width, height, fourcc,1519DRM_FORMAT_MOD_INVALID, fds, num_fds,1520strides, offsets, false, NULL, loaderPrivate);1521}15221523static boolean1524dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max,1525uint64_t *modifiers, unsigned int *external_only,1526int *count)1527{1528struct dri_screen *screen = dri_screen(_screen);1529struct pipe_screen *pscreen = screen->base.screen;1530const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc);1531enum pipe_format format;15321533if (!map)1534return false;15351536format = map->pipe_format;15371538if (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,1539PIPE_BIND_RENDER_TARGET) ||1540pscreen->is_format_supported(pscreen, format, screen->target, 0, 0,1541PIPE_BIND_SAMPLER_VIEW) ||1542dri2_yuv_dma_buf_supported(screen, map)) {1543if (pscreen->query_dmabuf_modifiers != NULL)1544pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers,1545external_only, count);1546else1547*count = 0;1548return true;1549}1550return false;1551}15521553static boolean1554dri2_query_dma_buf_format_modifier_attribs(__DRIscreen *_screen,1555uint32_t fourcc, uint64_t modifier,1556int attrib, uint64_t *value)1557{1558struct dri_screen *screen = dri_screen(_screen);1559struct pipe_screen *pscreen = screen->base.screen;15601561if (!pscreen->query_dmabuf_modifiers)1562return false;15631564switch (attrib) {1565case __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: {1566uint64_t mod_planes = dri2_get_modifier_num_planes(_screen, modifier,1567fourcc);1568if (mod_planes > 0)1569*value = mod_planes;1570return mod_planes > 0;1571}1572default:1573return false;1574}1575}15761577static __DRIimage *1578dri2_from_dma_bufs(__DRIscreen *screen,1579int width, int height, int fourcc,1580int *fds, int num_fds,1581int *strides, int *offsets,1582enum __DRIYUVColorSpace yuv_color_space,1583enum __DRISampleRange sample_range,1584enum __DRIChromaSiting horizontal_siting,1585enum __DRIChromaSiting vertical_siting,1586unsigned *error,1587void *loaderPrivate)1588{1589__DRIimage *img;15901591img = dri2_create_image_from_fd(screen, width, height, fourcc,1592DRM_FORMAT_MOD_INVALID, fds, num_fds,1593strides, offsets, false, error, loaderPrivate);1594if (img == NULL)1595return NULL;15961597img->yuv_color_space = yuv_color_space;1598img->sample_range = sample_range;1599img->horizontal_siting = horizontal_siting;1600img->vertical_siting = vertical_siting;16011602*error = __DRI_IMAGE_ERROR_SUCCESS;1603return img;1604}16051606static __DRIimage *1607dri2_from_dma_bufs2(__DRIscreen *screen,1608int width, int height, int fourcc,1609uint64_t modifier, int *fds, int num_fds,1610int *strides, int *offsets,1611enum __DRIYUVColorSpace yuv_color_space,1612enum __DRISampleRange sample_range,1613enum __DRIChromaSiting horizontal_siting,1614enum __DRIChromaSiting vertical_siting,1615unsigned *error,1616void *loaderPrivate)1617{1618__DRIimage *img;16191620img = dri2_create_image_from_fd(screen, width, height, fourcc,1621modifier, fds, num_fds, strides, offsets,1622false, error, loaderPrivate);1623if (img == NULL)1624return NULL;16251626img->yuv_color_space = yuv_color_space;1627img->sample_range = sample_range;1628img->horizontal_siting = horizontal_siting;1629img->vertical_siting = vertical_siting;16301631*error = __DRI_IMAGE_ERROR_SUCCESS;1632return img;1633}16341635static __DRIimage *1636dri2_from_dma_bufs3(__DRIscreen *screen,1637int width, int height, int fourcc,1638uint64_t modifier, int *fds, int num_fds,1639int *strides, int *offsets,1640enum __DRIYUVColorSpace yuv_color_space,1641enum __DRISampleRange sample_range,1642enum __DRIChromaSiting horizontal_siting,1643enum __DRIChromaSiting vertical_siting,1644uint32_t flags,1645unsigned *error,1646void *loaderPrivate)1647{1648__DRIimage *img;16491650img = dri2_create_image_from_fd(screen, width, height, fourcc,1651modifier, fds, num_fds, strides, offsets,1652flags & __DRI_IMAGE_PROTECTED_CONTENT_FLAG,1653error, loaderPrivate);1654if (img == NULL)1655return NULL;16561657img->yuv_color_space = yuv_color_space;1658img->sample_range = sample_range;1659img->horizontal_siting = horizontal_siting;1660img->vertical_siting = vertical_siting;16611662*error = __DRI_IMAGE_ERROR_SUCCESS;1663return img;1664}16651666static void1667dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src,1668int dstx0, int dsty0, int dstwidth, int dstheight,1669int srcx0, int srcy0, int srcwidth, int srcheight,1670int flush_flag)1671{1672struct dri_context *ctx = dri_context(context);1673struct pipe_context *pipe = ctx->st->pipe;1674struct pipe_screen *screen;1675struct pipe_fence_handle *fence;1676struct pipe_blit_info blit;16771678if (!dst || !src)1679return;16801681memset(&blit, 0, sizeof(blit));1682blit.dst.resource = dst->texture;1683blit.dst.box.x = dstx0;1684blit.dst.box.y = dsty0;1685blit.dst.box.width = dstwidth;1686blit.dst.box.height = dstheight;1687blit.dst.box.depth = 1;1688blit.dst.format = dst->texture->format;1689blit.src.resource = src->texture;1690blit.src.box.x = srcx0;1691blit.src.box.y = srcy0;1692blit.src.box.width = srcwidth;1693blit.src.box.height = srcheight;1694blit.src.box.depth = 1;1695blit.src.format = src->texture->format;1696blit.mask = PIPE_MASK_RGBA;1697blit.filter = PIPE_TEX_FILTER_NEAREST;16981699pipe->blit(pipe, &blit);17001701if (flush_flag == __BLIT_FLAG_FLUSH) {1702pipe->flush_resource(pipe, dst->texture);1703ctx->st->flush(ctx->st, 0, NULL, NULL, NULL);1704} else if (flush_flag == __BLIT_FLAG_FINISH) {1705screen = dri_screen(ctx->sPriv)->base.screen;1706pipe->flush_resource(pipe, dst->texture);1707ctx->st->flush(ctx->st, 0, &fence, NULL, NULL);1708(void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE);1709screen->fence_reference(screen, &fence, NULL);1710}1711}17121713static void *1714dri2_map_image(__DRIcontext *context, __DRIimage *image,1715int x0, int y0, int width, int height,1716unsigned int flags, int *stride, void **data)1717{1718struct dri_context *ctx = dri_context(context);1719struct pipe_context *pipe = ctx->st->pipe;1720enum pipe_map_flags pipe_access = 0;1721struct pipe_transfer *trans;1722void *map;17231724if (!image || !data || *data)1725return NULL;17261727unsigned plane = image->plane;1728if (plane >= dri2_get_mapping_by_format(image->dri_format)->nplanes)1729return NULL;17301731struct pipe_resource *resource = image->texture;1732while (plane--)1733resource = resource->next;17341735if (flags & __DRI_IMAGE_TRANSFER_READ)1736pipe_access |= PIPE_MAP_READ;1737if (flags & __DRI_IMAGE_TRANSFER_WRITE)1738pipe_access |= PIPE_MAP_WRITE;17391740map = pipe_texture_map(pipe, resource, 0, 0, pipe_access, x0, y0,1741width, height, &trans);1742if (map) {1743*data = trans;1744*stride = trans->stride;1745}17461747return map;1748}17491750static void1751dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data)1752{1753struct dri_context *ctx = dri_context(context);1754struct pipe_context *pipe = ctx->st->pipe;17551756pipe_texture_unmap(pipe, (struct pipe_transfer *)data);1757}17581759static int1760dri2_get_capabilities(__DRIscreen *_screen)1761{1762struct dri_screen *screen = dri_screen(_screen);17631764return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0);1765}17661767/* The extension is modified during runtime if DRI_PRIME is detected */1768static const __DRIimageExtension dri2ImageExtensionTempl = {1769.base = { __DRI_IMAGE, 19 },17701771.createImageFromName = dri2_create_image_from_name,1772.createImageFromRenderbuffer = dri2_create_image_from_renderbuffer,1773.destroyImage = dri2_destroy_image,1774.createImage = dri2_create_image,1775.queryImage = dri2_query_image,1776.dupImage = dri2_dup_image,1777.validateUsage = dri2_validate_usage,1778.createImageFromNames = dri2_from_names,1779.fromPlanar = dri2_from_planar,1780.createImageFromTexture = dri2_create_from_texture,1781.createImageFromFds = NULL,1782.createImageFromDmaBufs = NULL,1783.blitImage = dri2_blit_image,1784.getCapabilities = dri2_get_capabilities,1785.mapImage = dri2_map_image,1786.unmapImage = dri2_unmap_image,1787.createImageWithModifiers = NULL,1788.createImageFromDmaBufs2 = NULL,1789.createImageFromDmaBufs3 = NULL,1790.queryDmaBufFormats = NULL,1791.queryDmaBufModifiers = NULL,1792.queryDmaBufFormatModifierAttribs = NULL,1793.createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2,1794.createImageWithModifiers2 = NULL,1795};17961797static const __DRIrobustnessExtension dri2Robustness = {1798.base = { __DRI2_ROBUSTNESS, 1 }1799};18001801static int1802dri2_interop_query_device_info(__DRIcontext *_ctx,1803struct mesa_glinterop_device_info *out)1804{1805struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen;18061807/* There is no version 0, thus we do not support it */1808if (out->version == 0)1809return MESA_GLINTEROP_INVALID_VERSION;18101811out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP);1812out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS);1813out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE);1814out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION);18151816out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID);1817out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID);18181819/* Instruct the caller that we support up-to version one of the interface */1820out->version = 1;18211822return MESA_GLINTEROP_SUCCESS;1823}18241825static int1826dri2_interop_export_object(__DRIcontext *_ctx,1827struct mesa_glinterop_export_in *in,1828struct mesa_glinterop_export_out *out)1829{1830struct st_context_iface *st = dri_context(_ctx)->st;1831struct pipe_screen *screen = st->pipe->screen;1832struct gl_context *ctx = ((struct st_context *)st)->ctx;1833struct pipe_resource *res = NULL;1834struct winsys_handle whandle;1835unsigned target, usage;1836boolean success;18371838/* There is no version 0, thus we do not support it */1839if (in->version == 0 || out->version == 0)1840return MESA_GLINTEROP_INVALID_VERSION;18411842/* Validate the target. */1843switch (in->target) {1844case GL_TEXTURE_BUFFER:1845case GL_TEXTURE_1D:1846case GL_TEXTURE_2D:1847case GL_TEXTURE_3D:1848case GL_TEXTURE_RECTANGLE:1849case GL_TEXTURE_1D_ARRAY:1850case GL_TEXTURE_2D_ARRAY:1851case GL_TEXTURE_CUBE_MAP_ARRAY:1852case GL_TEXTURE_CUBE_MAP:1853case GL_TEXTURE_2D_MULTISAMPLE:1854case GL_TEXTURE_2D_MULTISAMPLE_ARRAY:1855case GL_TEXTURE_EXTERNAL_OES:1856case GL_RENDERBUFFER:1857case GL_ARRAY_BUFFER:1858target = in->target;1859break;1860case GL_TEXTURE_CUBE_MAP_POSITIVE_X:1861case GL_TEXTURE_CUBE_MAP_NEGATIVE_X:1862case GL_TEXTURE_CUBE_MAP_POSITIVE_Y:1863case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y:1864case GL_TEXTURE_CUBE_MAP_POSITIVE_Z:1865case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z:1866target = GL_TEXTURE_CUBE_MAP;1867break;1868default:1869return MESA_GLINTEROP_INVALID_TARGET;1870}18711872/* Validate the simple case of miplevel. */1873if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) &&1874in->miplevel != 0)1875return MESA_GLINTEROP_INVALID_MIP_LEVEL;18761877/* Validate the OpenGL object and get pipe_resource. */1878simple_mtx_lock(&ctx->Shared->Mutex);18791880if (target == GL_ARRAY_BUFFER) {1881/* Buffer objects.1882*1883* The error checking is based on the documentation of1884* clCreateFromGLBuffer from OpenCL 2.0 SDK.1885*/1886struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj);18871888/* From OpenCL 2.0 SDK, clCreateFromGLBuffer:1889* "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is1890* a GL buffer object but does not have an existing data store or1891* the size of the buffer is 0."1892*/1893if (!buf || buf->Size == 0) {1894simple_mtx_unlock(&ctx->Shared->Mutex);1895return MESA_GLINTEROP_INVALID_OBJECT;1896}18971898res = st_buffer_object(buf)->buffer;1899if (!res) {1900/* this shouldn't happen */1901simple_mtx_unlock(&ctx->Shared->Mutex);1902return MESA_GLINTEROP_INVALID_OBJECT;1903}19041905out->buf_offset = 0;1906out->buf_size = buf->Size;19071908buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;1909} else if (target == GL_RENDERBUFFER) {1910/* Renderbuffers.1911*1912* The error checking is based on the documentation of1913* clCreateFromGLRenderbuffer from OpenCL 2.0 SDK.1914*/1915struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj);19161917/* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:1918* "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer1919* object or if the width or height of renderbuffer is zero."1920*/1921if (!rb || rb->Width == 0 || rb->Height == 0) {1922simple_mtx_unlock(&ctx->Shared->Mutex);1923return MESA_GLINTEROP_INVALID_OBJECT;1924}19251926/* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:1927* "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL1928* renderbuffer object."1929*/1930if (rb->NumSamples > 1) {1931simple_mtx_unlock(&ctx->Shared->Mutex);1932return MESA_GLINTEROP_INVALID_OPERATION;1933}19341935/* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer:1936* "CL_OUT_OF_RESOURCES if there is a failure to allocate resources1937* required by the OpenCL implementation on the device."1938*/1939res = st_renderbuffer(rb)->texture;1940if (!res) {1941simple_mtx_unlock(&ctx->Shared->Mutex);1942return MESA_GLINTEROP_OUT_OF_RESOURCES;1943}19441945out->internal_format = rb->InternalFormat;1946out->view_minlevel = 0;1947out->view_numlevels = 1;1948out->view_minlayer = 0;1949out->view_numlayers = 1;1950} else {1951/* Texture objects.1952*1953* The error checking is based on the documentation of1954* clCreateFromGLTexture from OpenCL 2.0 SDK.1955*/1956struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj);19571958if (obj)1959_mesa_test_texobj_completeness(ctx, obj);19601961/* From OpenCL 2.0 SDK, clCreateFromGLTexture:1962* "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose1963* type matches texture_target, if the specified miplevel of texture1964* is not defined, or if the width or height of the specified1965* miplevel is zero or if the GL texture object is incomplete."1966*/1967if (!obj ||1968obj->Target != target ||1969!obj->_BaseComplete ||1970(in->miplevel > 0 && !obj->_MipmapComplete)) {1971simple_mtx_unlock(&ctx->Shared->Mutex);1972return MESA_GLINTEROP_INVALID_OBJECT;1973}19741975if (target == GL_TEXTURE_BUFFER) {1976struct st_buffer_object *stBuf =1977st_buffer_object(obj->BufferObject);19781979if (!stBuf || !stBuf->buffer) {1980/* this shouldn't happen */1981simple_mtx_unlock(&ctx->Shared->Mutex);1982return MESA_GLINTEROP_INVALID_OBJECT;1983}1984res = stBuf->buffer;19851986out->internal_format = obj->BufferObjectFormat;1987out->buf_offset = obj->BufferOffset;1988out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size :1989obj->BufferSize;19901991obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE;1992} else {1993/* From OpenCL 2.0 SDK, clCreateFromGLTexture:1994* "CL_INVALID_MIP_LEVEL if miplevel is less than the value of1995* levelbase (for OpenGL implementations) or zero (for OpenGL ES1996* implementations); or greater than the value of q (for both OpenGL1997* and OpenGL ES). levelbase and q are defined for the texture in1998* section 3.8.10 (Texture Completeness) of the OpenGL 2.11999* specification and section 3.7.10 of the OpenGL ES 2.0."2000*/2001if (in->miplevel < obj->Attrib.BaseLevel || in->miplevel > obj->_MaxLevel) {2002simple_mtx_unlock(&ctx->Shared->Mutex);2003return MESA_GLINTEROP_INVALID_MIP_LEVEL;2004}20052006if (!st_finalize_texture(ctx, st->pipe, obj, 0)) {2007simple_mtx_unlock(&ctx->Shared->Mutex);2008return MESA_GLINTEROP_OUT_OF_RESOURCES;2009}20102011res = st_get_texobj_resource(obj);2012if (!res) {2013/* Incomplete texture buffer object? This shouldn't really occur. */2014simple_mtx_unlock(&ctx->Shared->Mutex);2015return MESA_GLINTEROP_INVALID_OBJECT;2016}20172018out->internal_format = obj->Image[0][0]->InternalFormat;2019out->view_minlevel = obj->Attrib.MinLevel;2020out->view_numlevels = obj->Attrib.NumLevels;2021out->view_minlayer = obj->Attrib.MinLayer;2022out->view_numlayers = obj->Attrib.NumLayers;2023}2024}20252026/* Get the handle. */2027switch (in->access) {2028case MESA_GLINTEROP_ACCESS_READ_ONLY:2029usage = 0;2030break;2031case MESA_GLINTEROP_ACCESS_READ_WRITE:2032case MESA_GLINTEROP_ACCESS_WRITE_ONLY:2033usage = PIPE_HANDLE_USAGE_SHADER_WRITE;2034break;2035default:2036usage = 0;2037}20382039memset(&whandle, 0, sizeof(whandle));2040whandle.type = WINSYS_HANDLE_TYPE_FD;20412042success = screen->resource_get_handle(screen, st->pipe, res, &whandle,2043usage);2044simple_mtx_unlock(&ctx->Shared->Mutex);20452046if (!success)2047return MESA_GLINTEROP_OUT_OF_HOST_MEMORY;20482049out->dmabuf_fd = whandle.handle;2050out->out_driver_data_written = 0;20512052if (res->target == PIPE_BUFFER)2053out->buf_offset += whandle.offset;20542055/* Instruct the caller that we support up-to version one of the interface */2056in->version = 1;2057out->version = 1;20582059return MESA_GLINTEROP_SUCCESS;2060}20612062static const __DRI2interopExtension dri2InteropExtension = {2063.base = { __DRI2_INTEROP, 1 },2064.query_device_info = dri2_interop_query_device_info,2065.export_object = dri2_interop_export_object2066};20672068/**2069* \brief the DRI2bufferDamageExtension set_damage_region method2070*/2071static void2072dri2_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects)2073{2074struct dri_drawable *drawable = dri_drawable(dPriv);2075struct pipe_box *boxes = NULL;20762077if (nrects) {2078boxes = CALLOC(nrects, sizeof(*boxes));2079assert(boxes);20802081for (unsigned int i = 0; i < nrects; i++) {2082int *rect = &rects[i * 4];20832084u_box_2d(rect[0], rect[1], rect[2], rect[3], &boxes[i]);2085}2086}20872088FREE(drawable->damage_rects);2089drawable->damage_rects = boxes;2090drawable->num_damage_rects = nrects;20912092/* Only apply the damage region if the BACK_LEFT texture is up-to-date. */2093if (drawable->texture_stamp == drawable->dPriv->lastStamp &&2094(drawable->texture_mask & (1 << ST_ATTACHMENT_BACK_LEFT))) {2095struct pipe_screen *screen = drawable->screen->base.screen;2096struct pipe_resource *resource;20972098if (drawable->stvis.samples > 1)2099resource = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT];2100else2101resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT];21022103screen->set_damage_region(screen, resource,2104drawable->num_damage_rects,2105drawable->damage_rects);2106}2107}21082109static const __DRI2bufferDamageExtension dri2BufferDamageExtensionTempl = {2110.base = { __DRI2_BUFFER_DAMAGE, 1 },2111};21122113/**2114* \brief the DRI2ConfigQueryExtension configQueryb method2115*/2116static int2117dri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var,2118unsigned char *val)2119{2120struct dri_screen *screen = dri_screen(sPriv);21212122if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL))2123return dri2ConfigQueryExtension.configQueryb(sPriv, var, val);21242125*val = driQueryOptionb(&screen->dev->option_cache, var);21262127return 0;2128}21292130/**2131* \brief the DRI2ConfigQueryExtension configQueryi method2132*/2133static int2134dri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val)2135{2136struct dri_screen *screen = dri_screen(sPriv);21372138if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) &&2139!driCheckOption(&screen->dev->option_cache, var, DRI_ENUM))2140return dri2ConfigQueryExtension.configQueryi(sPriv, var, val);21412142*val = driQueryOptioni(&screen->dev->option_cache, var);21432144return 0;2145}21462147/**2148* \brief the DRI2ConfigQueryExtension configQueryf method2149*/2150static int2151dri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val)2152{2153struct dri_screen *screen = dri_screen(sPriv);21542155if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT))2156return dri2ConfigQueryExtension.configQueryf(sPriv, var, val);21572158*val = driQueryOptionf(&screen->dev->option_cache, var);21592160return 0;2161}21622163/**2164* \brief the DRI2ConfigQueryExtension configQuerys method2165*/2166static int2167dri2GalliumConfigQuerys(__DRIscreen *sPriv, const char *var, char **val)2168{2169struct dri_screen *screen = dri_screen(sPriv);21702171if (!driCheckOption(&screen->dev->option_cache, var, DRI_STRING))2172return dri2ConfigQueryExtension.configQuerys(sPriv, var, val);21732174*val = driQueryOptionstr(&screen->dev->option_cache, var);21752176return 0;2177}21782179/**2180* \brief the DRI2ConfigQueryExtension struct.2181*2182* We first query the driver option cache. Then the dri2 option cache.2183*/2184static const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = {2185.base = { __DRI2_CONFIG_QUERY, 2 },21862187.configQueryb = dri2GalliumConfigQueryb,2188.configQueryi = dri2GalliumConfigQueryi,2189.configQueryf = dri2GalliumConfigQueryf,2190.configQuerys = dri2GalliumConfigQuerys,2191};21922193/**2194* \brief the DRI2blobExtension set_cache_funcs method2195*/2196static void2197set_blob_cache_funcs(__DRIscreen *sPriv, __DRIblobCacheSet set,2198__DRIblobCacheGet get)2199{2200struct dri_screen *screen = dri_screen(sPriv);2201struct pipe_screen *pscreen = screen->base.screen;22022203if (!pscreen->get_disk_shader_cache)2204return;22052206struct disk_cache *cache = pscreen->get_disk_shader_cache(pscreen);22072208if (!cache)2209return;22102211disk_cache_set_callbacks(cache, set, get);2212}22132214static const __DRI2blobExtension driBlobExtension = {2215.base = { __DRI2_BLOB, 1 },2216.set_cache_funcs = set_blob_cache_funcs2217};22182219static const __DRImutableRenderBufferDriverExtension driMutableRenderBufferExtension = {2220.base = { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1 },2221};22222223/*2224* Backend function init_screen.2225*/22262227static const __DRIextension *dri_screen_extensions_base[] = {2228&driTexBufferExtension.base,2229&dri2FlushExtension.base,2230&dri2RendererQueryExtension.base,2231&dri2GalliumConfigQueryExtension.base,2232&dri2ThrottleExtension.base,2233&dri2FenceExtension.base,2234&dri2InteropExtension.base,2235&dri2NoErrorExtension.base,2236&driBlobExtension.base,2237&driMutableRenderBufferExtension.base,2238};22392240/**2241* Set up the DRI extension list for this screen based on its underlying2242* gallium screen's capabilities.2243*/2244static void2245dri2_init_screen_extensions(struct dri_screen *screen,2246struct pipe_screen *pscreen,2247bool is_kms_screen)2248{2249const __DRIextension **nExt;22502251STATIC_ASSERT(sizeof(screen->screen_extensions) >=2252sizeof(dri_screen_extensions_base));2253memcpy(&screen->screen_extensions, dri_screen_extensions_base,2254sizeof(dri_screen_extensions_base));2255screen->sPriv->extensions = screen->screen_extensions;22562257/* Point nExt at the end of the extension list */2258nExt = &screen->screen_extensions[ARRAY_SIZE(dri_screen_extensions_base)];22592260screen->image_extension = dri2ImageExtensionTempl;2261if (pscreen->resource_create_with_modifiers) {2262screen->image_extension.createImageWithModifiers =2263dri2_create_image_with_modifiers;2264screen->image_extension.createImageWithModifiers2 =2265dri2_create_image_with_modifiers2;2266}22672268if (pscreen->get_param(pscreen, PIPE_CAP_DMABUF)) {2269uint64_t cap;22702271if (drmGetCap(screen->sPriv->fd, DRM_CAP_PRIME, &cap) == 0 &&2272(cap & DRM_PRIME_CAP_IMPORT)) {2273screen->image_extension.createImageFromFds = dri2_from_fds;2274screen->image_extension.createImageFromDmaBufs = dri2_from_dma_bufs;2275screen->image_extension.createImageFromDmaBufs2 = dri2_from_dma_bufs2;2276screen->image_extension.createImageFromDmaBufs3 = dri2_from_dma_bufs3;2277screen->image_extension.queryDmaBufFormats =2278dri2_query_dma_buf_formats;2279screen->image_extension.queryDmaBufModifiers =2280dri2_query_dma_buf_modifiers;2281if (!is_kms_screen) {2282screen->image_extension.queryDmaBufFormatModifierAttribs =2283dri2_query_dma_buf_format_modifier_attribs;2284}2285}2286}2287*nExt++ = &screen->image_extension.base;22882289if (!is_kms_screen) {2290screen->buffer_damage_extension = dri2BufferDamageExtensionTempl;2291if (pscreen->set_damage_region)2292screen->buffer_damage_extension.set_damage_region =2293dri2_set_damage_region;2294*nExt++ = &screen->buffer_damage_extension.base;22952296if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) {2297*nExt++ = &dri2Robustness.base;2298screen->has_reset_status_query = true;2299}2300}23012302/* Ensure the extension list didn't overrun its buffer and is still2303* NULL-terminated */2304assert(nExt - screen->screen_extensions <=2305ARRAY_SIZE(screen->screen_extensions) - 1);2306assert(!*nExt);2307}23082309/**2310* This is the driver specific part of the createNewScreen entry point.2311*2312* Returns the struct gl_config supported by this driver.2313*/2314static const __DRIconfig **2315dri2_init_screen(__DRIscreen * sPriv)2316{2317const __DRIconfig **configs;2318struct dri_screen *screen;2319struct pipe_screen *pscreen = NULL;23202321screen = CALLOC_STRUCT(dri_screen);2322if (!screen)2323return NULL;23242325screen->sPriv = sPriv;2326screen->fd = sPriv->fd;2327(void) mtx_init(&screen->opencl_func_mutex, mtx_plain);23282329sPriv->driverPrivate = (void *)screen;23302331if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) {2332dri_init_options(screen);23332334pscreen = pipe_loader_create_screen(screen->dev);2335}23362337if (!pscreen)2338goto release_pipe;23392340screen->throttle = pscreen->get_param(pscreen, PIPE_CAP_THROTTLE);23412342dri2_init_screen_extensions(screen, pscreen, false);23432344configs = dri_init_screen_helper(screen, pscreen);2345if (!configs)2346goto destroy_screen;23472348screen->can_share_buffer = true;2349screen->auto_fake_front = dri_with_format(sPriv);2350screen->broken_invalidate = !sPriv->dri2.useInvalidate;2351screen->lookup_egl_image = dri2_lookup_egl_image;23522353return configs;23542355destroy_screen:2356dri_destroy_screen_helper(screen);23572358release_pipe:2359if (screen->dev)2360pipe_loader_release(&screen->dev, 1);23612362FREE(screen);2363return NULL;2364}23652366/**2367* This is the driver specific part of the createNewScreen entry point.2368*2369* Returns the struct gl_config supported by this driver.2370*/2371static const __DRIconfig **2372dri_kms_init_screen(__DRIscreen * sPriv)2373{2374#if defined(GALLIUM_SOFTPIPE)2375const __DRIconfig **configs;2376struct dri_screen *screen;2377struct pipe_screen *pscreen = NULL;23782379screen = CALLOC_STRUCT(dri_screen);2380if (!screen)2381return NULL;23822383screen->sPriv = sPriv;2384screen->fd = sPriv->fd;23852386sPriv->driverPrivate = (void *)screen;23872388if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd)) {2389dri_init_options(screen);2390pscreen = pipe_loader_create_screen(screen->dev);2391}23922393if (!pscreen)2394goto release_pipe;23952396dri2_init_screen_extensions(screen, pscreen, true);23972398configs = dri_init_screen_helper(screen, pscreen);2399if (!configs)2400goto destroy_screen;24012402screen->can_share_buffer = false;2403screen->auto_fake_front = dri_with_format(sPriv);2404screen->broken_invalidate = !sPriv->dri2.useInvalidate;2405screen->lookup_egl_image = dri2_lookup_egl_image;24062407return configs;24082409destroy_screen:2410dri_destroy_screen_helper(screen);24112412release_pipe:2413if (screen->dev)2414pipe_loader_release(&screen->dev, 1);24152416FREE(screen);2417#endif // GALLIUM_SOFTPIPE2418return NULL;2419}24202421static boolean2422dri2_create_buffer(__DRIscreen * sPriv,2423__DRIdrawable * dPriv,2424const struct gl_config * visual, boolean isPixmap)2425{2426struct dri_drawable *drawable = NULL;24272428if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap))2429return FALSE;24302431drawable = dPriv->driverPrivate;24322433drawable->allocate_textures = dri2_allocate_textures;2434drawable->flush_frontbuffer = dri2_flush_frontbuffer;2435drawable->update_tex_buffer = dri2_update_tex_buffer;2436drawable->flush_swapbuffers = dri2_flush_swapbuffers;24372438return TRUE;2439}24402441/**2442* DRI driver virtual function table.2443*2444* DRI versions differ in their implementation of init_screen and swap_buffers.2445*/2446const struct __DriverAPIRec galliumdrm_driver_api = {2447.InitScreen = dri2_init_screen,2448.DestroyScreen = dri_destroy_screen,2449.CreateContext = dri_create_context,2450.DestroyContext = dri_destroy_context,2451.CreateBuffer = dri2_create_buffer,2452.DestroyBuffer = dri_destroy_buffer,2453.MakeCurrent = dri_make_current,2454.UnbindContext = dri_unbind_context,24552456.AllocateBuffer = dri2_allocate_buffer,2457.ReleaseBuffer = dri2_release_buffer,2458};24592460/**2461* DRI driver virtual function table.2462*2463* KMS/DRM version of the DriverAPI above sporting a different InitScreen2464* hook. The latter is used to explicitly initialise the kms_swrast driver2465* rather than selecting the approapriate driver as suggested by the loader.2466*/2467const struct __DriverAPIRec dri_kms_driver_api = {2468.InitScreen = dri_kms_init_screen,2469.DestroyScreen = dri_destroy_screen,2470.CreateContext = dri_create_context,2471.DestroyContext = dri_destroy_context,2472.CreateBuffer = dri2_create_buffer,2473.DestroyBuffer = dri_destroy_buffer,2474.MakeCurrent = dri_make_current,2475.UnbindContext = dri_unbind_context,24762477.AllocateBuffer = dri2_allocate_buffer,2478.ReleaseBuffer = dri2_release_buffer,2479};24802481/* This is the table of extensions that the loader will dlsym() for. */2482const __DRIextension *galliumdrm_driver_extensions[] = {2483&driCoreExtension.base,2484&driImageDriverExtension.base,2485&driDRI2Extension.base,2486&gallium_config_options.base,2487NULL2488};24892490/* vim: set sw=3 ts=8 sts=3 expandtab: */249124922493