1/* 2 * Mesa 3-D graphics library 3 * 4 * Copyright 2009, VMware, Inc. 5 * All Rights Reserved. 6 * Copyright (C) 2010 LunarG Inc. 7 * 8 * Permission is hereby granted, free of charge, to any person obtaining a 9 * copy of this software and associated documentation files (the "Software"), 10 * to deal in the Software without restriction, including without limitation 11 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 12 * and/or sell copies of the Software, and to permit persons to whom the 13 * Software is furnished to do so, subject to the following conditions: 14 * 15 * The above copyright notice and this permission notice shall be included 16 * in all copies or substantial portions of the Software. 17 * 18 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 19 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 20 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 21 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR 22 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 23 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 24 * OTHER DEALINGS IN THE SOFTWARE. 25 * 26 * Authors: 27 * Keith Whitwell <keithw@vmware.com> Jakob Bornecrantz 28 * <wallbraker@gmail.com> Chia-I Wu <olv@lunarg.com> 29 */ 30 31#include <xf86drm.h> 32#include "GL/mesa_glinterop.h" 33#include "util/disk_cache.h" 34#include "util/u_memory.h" 35#include "util/u_inlines.h" 36#include "util/format/u_format.h" 37#include "util/u_debug.h" 38#include "util/libsync.h" 39#include "util/os_file.h" 40#include "frontend/drm_driver.h" 41#include "state_tracker/st_format.h" 42#include "state_tracker/st_cb_texture.h" 43#include "state_tracker/st_texture.h" 44#include "state_tracker/st_context.h" 45#include "pipe-loader/pipe_loader.h" 46#include "main/bufferobj.h" 47#include "main/texobj.h" 48 49#include "dri_util.h" 50 51#include "dri_helpers.h" 52#include "dri_drawable.h" 53#include "dri_query_renderer.h" 54 55#include "drm-uapi/drm_fourcc.h" 56 57struct dri2_buffer 58{ 59 __DRIbuffer base; 60 struct pipe_resource *resource; 61}; 62 63static inline struct dri2_buffer * 64dri2_buffer(__DRIbuffer * driBufferPriv) 65{ 66 return (struct dri2_buffer *) driBufferPriv; 67} 68 69/** 70 * DRI2 flush extension. 71 */ 72static void 73dri2_flush_drawable(__DRIdrawable *dPriv) 74{ 75 dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1); 76} 77 78static void 79dri2_invalidate_drawable(__DRIdrawable *dPriv) 80{ 81 struct dri_drawable *drawable = dri_drawable(dPriv); 82 83 dPriv->dri2.stamp++; 84 drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; 85 drawable->texture_mask = 0; 86 87 p_atomic_inc(&drawable->base.stamp); 88} 89 90static const __DRI2flushExtension dri2FlushExtension = { 91 .base = { __DRI2_FLUSH, 4 }, 92 93 .flush = dri2_flush_drawable, 94 .invalidate = dri2_invalidate_drawable, 95 .flush_with_flags = dri_flush, 96}; 97 98/** 99 * Retrieve __DRIbuffer from the DRI loader. 100 */ 101static __DRIbuffer * 102dri2_drawable_get_buffers(struct dri_drawable *drawable, 103 const enum st_attachment_type *atts, 104 unsigned *count) 105{ 106 __DRIdrawable *dri_drawable = drawable->dPriv; 107 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; 108 boolean with_format; 109 __DRIbuffer *buffers; 110 int num_buffers; 111 unsigned attachments[__DRI_BUFFER_COUNT]; 112 unsigned num_attachments, i; 113 114 assert(loader); 115 assert(*count <= __DRI_BUFFER_COUNT); 116 with_format = dri_with_format(drawable->sPriv); 117 118 num_attachments = 0; 119 120 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ 121 if (!with_format) 122 attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; 123 124 for (i = 0; i < *count; i++) { 125 enum pipe_format format; 126 unsigned bind; 127 int att, depth; 128 129 dri_drawable_get_format(drawable, atts[i], &format, &bind); 130 if (format == PIPE_FORMAT_NONE) 131 continue; 132 133 switch (atts[i]) { 134 case ST_ATTACHMENT_FRONT_LEFT: 135 /* already added */ 136 if (!with_format) 137 continue; 138 att = __DRI_BUFFER_FRONT_LEFT; 139 break; 140 case ST_ATTACHMENT_BACK_LEFT: 141 att = __DRI_BUFFER_BACK_LEFT; 142 break; 143 case ST_ATTACHMENT_FRONT_RIGHT: 144 att = __DRI_BUFFER_FRONT_RIGHT; 145 break; 146 case ST_ATTACHMENT_BACK_RIGHT: 147 att = __DRI_BUFFER_BACK_RIGHT; 148 break; 149 default: 150 continue; 151 } 152 153 /* 154 * In this switch statement we must support all formats that 155 * may occur as the stvis->color_format. 156 */ 157 switch(format) { 158 case PIPE_FORMAT_R16G16B16A16_FLOAT: 159 depth = 64; 160 break; 161 case PIPE_FORMAT_R16G16B16X16_FLOAT: 162 depth = 48; 163 break; 164 case PIPE_FORMAT_B10G10R10A2_UNORM: 165 case PIPE_FORMAT_R10G10B10A2_UNORM: 166 case PIPE_FORMAT_BGRA8888_UNORM: 167 case PIPE_FORMAT_RGBA8888_UNORM: 168 depth = 32; 169 break; 170 case PIPE_FORMAT_R10G10B10X2_UNORM: 171 case PIPE_FORMAT_B10G10R10X2_UNORM: 172 depth = 30; 173 break; 174 case PIPE_FORMAT_BGRX8888_UNORM: 175 case PIPE_FORMAT_RGBX8888_UNORM: 176 depth = 24; 177 break; 178 case PIPE_FORMAT_B5G6R5_UNORM: 179 depth = 16; 180 break; 181 default: 182 depth = util_format_get_blocksizebits(format); 183 assert(!"Unexpected format in dri2_drawable_get_buffers()"); 184 } 185 186 attachments[num_attachments++] = att; 187 if (with_format) { 188 attachments[num_attachments++] = depth; 189 } 190 } 191 192 if (with_format) { 193 num_attachments /= 2; 194 buffers = loader->getBuffersWithFormat(dri_drawable, 195 &dri_drawable->w, &dri_drawable->h, 196 attachments, num_attachments, 197 &num_buffers, dri_drawable->loaderPrivate); 198 } 199 else { 200 buffers = loader->getBuffers(dri_drawable, 201 &dri_drawable->w, &dri_drawable->h, 202 attachments, num_attachments, 203 &num_buffers, dri_drawable->loaderPrivate); 204 } 205 206 if (buffers) 207 *count = num_buffers; 208 209 return buffers; 210} 211 212bool 213dri_image_drawable_get_buffers(struct dri_drawable *drawable, 214 struct __DRIimageList *images, 215 const enum st_attachment_type *statts, 216 unsigned statts_count); 217bool 218dri_image_drawable_get_buffers(struct dri_drawable *drawable, 219 struct __DRIimageList *images, 220 const enum st_attachment_type *statts, 221 unsigned statts_count) 222{ 223 __DRIdrawable *dPriv = drawable->dPriv; 224 __DRIscreen *sPriv = drawable->sPriv; 225 unsigned int image_format = __DRI_IMAGE_FORMAT_NONE; 226 enum pipe_format pf; 227 uint32_t buffer_mask = 0; 228 unsigned i, bind; 229 230 for (i = 0; i < statts_count; i++) { 231 dri_drawable_get_format(drawable, statts[i], &pf, &bind); 232 if (pf == PIPE_FORMAT_NONE) 233 continue; 234 235 switch (statts[i]) { 236 case ST_ATTACHMENT_FRONT_LEFT: 237 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; 238 break; 239 case ST_ATTACHMENT_BACK_LEFT: 240 buffer_mask |= __DRI_IMAGE_BUFFER_BACK; 241 break; 242 default: 243 continue; 244 } 245 246 switch (pf) { 247 case PIPE_FORMAT_R16G16B16A16_FLOAT: 248 image_format = __DRI_IMAGE_FORMAT_ABGR16161616F; 249 break; 250 case PIPE_FORMAT_R16G16B16X16_FLOAT: 251 image_format = __DRI_IMAGE_FORMAT_XBGR16161616F; 252 break; 253 case PIPE_FORMAT_B5G5R5A1_UNORM: 254 image_format = __DRI_IMAGE_FORMAT_ARGB1555; 255 break; 256 case PIPE_FORMAT_B5G6R5_UNORM: 257 image_format = __DRI_IMAGE_FORMAT_RGB565; 258 break; 259 case PIPE_FORMAT_BGRX8888_UNORM: 260 image_format = __DRI_IMAGE_FORMAT_XRGB8888; 261 break; 262 case PIPE_FORMAT_BGRA8888_UNORM: 263 image_format = __DRI_IMAGE_FORMAT_ARGB8888; 264 break; 265 case PIPE_FORMAT_RGBX8888_UNORM: 266 image_format = __DRI_IMAGE_FORMAT_XBGR8888; 267 break; 268 case PIPE_FORMAT_RGBA8888_UNORM: 269 image_format = __DRI_IMAGE_FORMAT_ABGR8888; 270 break; 271 case PIPE_FORMAT_B10G10R10X2_UNORM: 272 image_format = __DRI_IMAGE_FORMAT_XRGB2101010; 273 break; 274 case PIPE_FORMAT_B10G10R10A2_UNORM: 275 image_format = __DRI_IMAGE_FORMAT_ARGB2101010; 276 break; 277 case PIPE_FORMAT_R10G10B10X2_UNORM: 278 image_format = __DRI_IMAGE_FORMAT_XBGR2101010; 279 break; 280 case PIPE_FORMAT_R10G10B10A2_UNORM: 281 image_format = __DRI_IMAGE_FORMAT_ABGR2101010; 282 break; 283 default: 284 image_format = __DRI_IMAGE_FORMAT_NONE; 285 break; 286 } 287 } 288 289 return (*sPriv->image.loader->getBuffers) (dPriv, image_format, 290 (uint32_t *) &drawable->base.stamp, 291 dPriv->loaderPrivate, buffer_mask, 292 images); 293} 294 295static __DRIbuffer * 296dri2_allocate_buffer(__DRIscreen *sPriv, 297 unsigned attachment, unsigned format, 298 int width, int height) 299{ 300 struct dri_screen *screen = dri_screen(sPriv); 301 struct dri2_buffer *buffer; 302 struct pipe_resource templ; 303 enum pipe_format pf; 304 unsigned bind = 0; 305 struct winsys_handle whandle; 306 307 /* struct pipe_resource height0 is 16-bit, avoid overflow */ 308 if (height > 0xffff) 309 return NULL; 310 311 switch (attachment) { 312 case __DRI_BUFFER_FRONT_LEFT: 313 case __DRI_BUFFER_FAKE_FRONT_LEFT: 314 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 315 break; 316 case __DRI_BUFFER_BACK_LEFT: 317 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 318 break; 319 case __DRI_BUFFER_DEPTH: 320 case __DRI_BUFFER_DEPTH_STENCIL: 321 case __DRI_BUFFER_STENCIL: 322 bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ 323 break; 324 } 325 326 /* because we get the handle and stride */ 327 bind |= PIPE_BIND_SHARED; 328 329 switch (format) { 330 case 64: 331 pf = PIPE_FORMAT_R16G16B16A16_FLOAT; 332 break; 333 case 48: 334 pf = PIPE_FORMAT_R16G16B16X16_FLOAT; 335 break; 336 case 32: 337 pf = PIPE_FORMAT_BGRA8888_UNORM; 338 break; 339 case 30: 340 pf = PIPE_FORMAT_B10G10R10X2_UNORM; 341 break; 342 case 24: 343 pf = PIPE_FORMAT_BGRX8888_UNORM; 344 break; 345 case 16: 346 pf = PIPE_FORMAT_Z16_UNORM; 347 break; 348 default: 349 return NULL; 350 } 351 352 buffer = CALLOC_STRUCT(dri2_buffer); 353 if (!buffer) 354 return NULL; 355 356 memset(&templ, 0, sizeof(templ)); 357 templ.bind = bind; 358 templ.format = pf; 359 templ.target = PIPE_TEXTURE_2D; 360 templ.last_level = 0; 361 templ.width0 = width; 362 templ.height0 = height; 363 templ.depth0 = 1; 364 templ.array_size = 1; 365 366 buffer->resource = 367 screen->base.screen->resource_create(screen->base.screen, &templ); 368 if (!buffer->resource) { 369 FREE(buffer); 370 return NULL; 371 } 372 373 memset(&whandle, 0, sizeof(whandle)); 374 if (screen->can_share_buffer) 375 whandle.type = WINSYS_HANDLE_TYPE_SHARED; 376 else 377 whandle.type = WINSYS_HANDLE_TYPE_KMS; 378 379 screen->base.screen->resource_get_handle(screen->base.screen, NULL, 380 buffer->resource, &whandle, 381 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); 382 383 buffer->base.attachment = attachment; 384 buffer->base.name = whandle.handle; 385 buffer->base.cpp = util_format_get_blocksize(pf); 386 buffer->base.pitch = whandle.stride; 387 388 return &buffer->base; 389} 390 391static void 392dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) 393{ 394 struct dri2_buffer *buffer = dri2_buffer(bPriv); 395 396 pipe_resource_reference(&buffer->resource, NULL); 397 FREE(buffer); 398} 399 400static void 401dri2_set_in_fence_fd(__DRIimage *img, int fd) 402{ 403 validate_fence_fd(fd); 404 validate_fence_fd(img->in_fence_fd); 405 sync_accumulate("dri", &img->in_fence_fd, fd); 406} 407 408static void 409handle_in_fence(__DRIcontext *context, __DRIimage *img) 410{ 411 struct dri_context *ctx = dri_context(context); 412 struct pipe_context *pipe = ctx->st->pipe; 413 struct pipe_fence_handle *fence; 414 int fd = img->in_fence_fd; 415 416 if (fd == -1) 417 return; 418 419 validate_fence_fd(fd); 420 421 img->in_fence_fd = -1; 422 423 pipe->create_fence_fd(pipe, &fence, fd, PIPE_FD_TYPE_NATIVE_SYNC); 424 pipe->fence_server_sync(pipe, fence); 425 pipe->screen->fence_reference(pipe->screen, &fence, NULL); 426 427 close(fd); 428} 429 430/* 431 * Backend functions for st_framebuffer interface. 432 */ 433 434static void 435dri2_allocate_textures(struct dri_context *ctx, 436 struct dri_drawable *drawable, 437 const enum st_attachment_type *statts, 438 unsigned statts_count) 439{ 440 __DRIscreen *sPriv = drawable->sPriv; 441 __DRIdrawable *dri_drawable = drawable->dPriv; 442 struct dri_screen *screen = dri_screen(sPriv); 443 struct pipe_resource templ; 444 boolean alloc_depthstencil = FALSE; 445 unsigned i, j, bind; 446 const __DRIimageLoaderExtension *image = sPriv->image.loader; 447 /* Image specific variables */ 448 struct __DRIimageList images; 449 /* Dri2 specific variables */ 450 __DRIbuffer *buffers = NULL; 451 struct winsys_handle whandle; 452 unsigned num_buffers = statts_count; 453 454 assert(num_buffers <= __DRI_BUFFER_COUNT); 455 456 /* First get the buffers from the loader */ 457 if (image) { 458 if (!dri_image_drawable_get_buffers(drawable, &images, 459 statts, statts_count)) 460 return; 461 } 462 else { 463 buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); 464 if (!buffers || (drawable->old_num == num_buffers && 465 drawable->old_w == dri_drawable->w && 466 drawable->old_h == dri_drawable->h && 467 memcmp(drawable->old, buffers, 468 sizeof(__DRIbuffer) * num_buffers) == 0)) 469 return; 470 } 471 472 /* Second clean useless resources*/ 473 474 /* See if we need a depth-stencil buffer. */ 475 for (i = 0; i < statts_count; i++) { 476 if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { 477 alloc_depthstencil = TRUE; 478 break; 479 } 480 } 481 482 /* Delete the resources we won't need. */ 483 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 484 /* Don't delete the depth-stencil buffer, we can reuse it. */ 485 if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) 486 continue; 487 488 /* Flush the texture before unreferencing, so that other clients can 489 * see what the driver has rendered. 490 */ 491 if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) { 492 struct pipe_context *pipe = ctx->st->pipe; 493 pipe->flush_resource(pipe, drawable->textures[i]); 494 } 495 496 pipe_resource_reference(&drawable->textures[i], NULL); 497 } 498 499 if (drawable->stvis.samples > 1) { 500 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 501 boolean del = TRUE; 502 503 /* Don't delete MSAA resources for the attachments which are enabled, 504 * we can reuse them. */ 505 for (j = 0; j < statts_count; j++) { 506 if (i == statts[j]) { 507 del = FALSE; 508 break; 509 } 510 } 511 512 if (del) { 513 pipe_resource_reference(&drawable->msaa_textures[i], NULL); 514 } 515 } 516 } 517 518 /* Third use the buffers retrieved to fill the drawable info */ 519 520 memset(&templ, 0, sizeof(templ)); 521 templ.target = screen->target; 522 templ.last_level = 0; 523 templ.depth0 = 1; 524 templ.array_size = 1; 525 526 if (image) { 527 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { 528 struct pipe_resource **buf = 529 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; 530 struct pipe_resource *texture = images.front->texture; 531 532 dri_drawable->w = texture->width0; 533 dri_drawable->h = texture->height0; 534 535 pipe_resource_reference(buf, texture); 536 handle_in_fence(ctx->cPriv, images.front); 537 } 538 539 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { 540 struct pipe_resource **buf = 541 &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; 542 struct pipe_resource *texture = images.back->texture; 543 544 dri_drawable->w = texture->width0; 545 dri_drawable->h = texture->height0; 546 547 pipe_resource_reference(buf, texture); 548 handle_in_fence(ctx->cPriv, images.back); 549 } 550 551 if (images.image_mask & __DRI_IMAGE_BUFFER_SHARED) { 552 struct pipe_resource **buf = 553 &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; 554 struct pipe_resource *texture = images.back->texture; 555 556 dri_drawable->w = texture->width0; 557 dri_drawable->h = texture->height0; 558 559 pipe_resource_reference(buf, texture); 560 handle_in_fence(ctx->cPriv, images.back); 561 562 ctx->is_shared_buffer_bound = true; 563 } else { 564 ctx->is_shared_buffer_bound = false; 565 } 566 567 /* Note: if there is both a back and a front buffer, 568 * then they have the same size. 569 */ 570 templ.width0 = dri_drawable->w; 571 templ.height0 = dri_drawable->h; 572 } 573 else { 574 memset(&whandle, 0, sizeof(whandle)); 575 576 /* Process DRI-provided buffers and get pipe_resources. */ 577 for (i = 0; i < num_buffers; i++) { 578 __DRIbuffer *buf = &buffers[i]; 579 enum st_attachment_type statt; 580 enum pipe_format format; 581 582 switch (buf->attachment) { 583 case __DRI_BUFFER_FRONT_LEFT: 584 if (!screen->auto_fake_front) { 585 continue; /* invalid attachment */ 586 } 587 FALLTHROUGH; 588 case __DRI_BUFFER_FAKE_FRONT_LEFT: 589 statt = ST_ATTACHMENT_FRONT_LEFT; 590 break; 591 case __DRI_BUFFER_BACK_LEFT: 592 statt = ST_ATTACHMENT_BACK_LEFT; 593 break; 594 default: 595 continue; /* invalid attachment */ 596 } 597 598 dri_drawable_get_format(drawable, statt, &format, &bind); 599 if (format == PIPE_FORMAT_NONE) 600 continue; 601 602 /* dri2_drawable_get_buffers has already filled dri_drawable->w 603 * and dri_drawable->h */ 604 templ.width0 = dri_drawable->w; 605 templ.height0 = dri_drawable->h; 606 templ.format = format; 607 templ.bind = bind; 608 whandle.handle = buf->name; 609 whandle.stride = buf->pitch; 610 whandle.offset = 0; 611 whandle.format = format; 612 whandle.modifier = DRM_FORMAT_MOD_INVALID; 613 if (screen->can_share_buffer) 614 whandle.type = WINSYS_HANDLE_TYPE_SHARED; 615 else 616 whandle.type = WINSYS_HANDLE_TYPE_KMS; 617 drawable->textures[statt] = 618 screen->base.screen->resource_from_handle(screen->base.screen, 619 &templ, &whandle, 620 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH); 621 assert(drawable->textures[statt]); 622 } 623 } 624 625 /* Allocate private MSAA colorbuffers. */ 626 if (drawable->stvis.samples > 1) { 627 for (i = 0; i < statts_count; i++) { 628 enum st_attachment_type statt = statts[i]; 629 630 if (statt == ST_ATTACHMENT_DEPTH_STENCIL) 631 continue; 632 633 if (drawable->textures[statt]) { 634 templ.format = drawable->textures[statt]->format; 635 templ.bind = drawable->textures[statt]->bind & 636 ~(PIPE_BIND_SCANOUT | PIPE_BIND_SHARED); 637 templ.nr_samples = drawable->stvis.samples; 638 templ.nr_storage_samples = drawable->stvis.samples; 639 640 /* Try to reuse the resource. 641 * (the other resource parameters should be constant) 642 */ 643 if (!drawable->msaa_textures[statt] || 644 drawable->msaa_textures[statt]->width0 != templ.width0 || 645 drawable->msaa_textures[statt]->height0 != templ.height0) { 646 /* Allocate a new one. */ 647 pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 648 649 drawable->msaa_textures[statt] = 650 screen->base.screen->resource_create(screen->base.screen, 651 &templ); 652 assert(drawable->msaa_textures[statt]); 653 654 /* If there are any MSAA resources, we should initialize them 655 * such that they contain the same data as the single-sample 656 * resources we just got from the X server. 657 * 658 * The reason for this is that the gallium frontend (and 659 * therefore the app) can access the MSAA resources only. 660 * The single-sample resources are not exposed 661 * to the gallium frontend. 662 * 663 */ 664 dri_pipe_blit(ctx->st->pipe, 665 drawable->msaa_textures[statt], 666 drawable->textures[statt]); 667 } 668 } 669 else { 670 pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 671 } 672 } 673 } 674 675 /* Allocate a private depth-stencil buffer. */ 676 if (alloc_depthstencil) { 677 enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL; 678 struct pipe_resource **zsbuf; 679 enum pipe_format format; 680 unsigned bind; 681 682 dri_drawable_get_format(drawable, statt, &format, &bind); 683 684 if (format) { 685 templ.format = format; 686 templ.bind = bind & ~PIPE_BIND_SHARED; 687 688 if (drawable->stvis.samples > 1) { 689 templ.nr_samples = drawable->stvis.samples; 690 templ.nr_storage_samples = drawable->stvis.samples; 691 zsbuf = &drawable->msaa_textures[statt]; 692 } 693 else { 694 templ.nr_samples = 0; 695 templ.nr_storage_samples = 0; 696 zsbuf = &drawable->textures[statt]; 697 } 698 699 /* Try to reuse the resource. 700 * (the other resource parameters should be constant) 701 */ 702 if (!*zsbuf || 703 (*zsbuf)->width0 != templ.width0 || 704 (*zsbuf)->height0 != templ.height0) { 705 /* Allocate a new one. */ 706 pipe_resource_reference(zsbuf, NULL); 707 *zsbuf = screen->base.screen->resource_create(screen->base.screen, 708 &templ); 709 assert(*zsbuf); 710 } 711 } 712 else { 713 pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 714 pipe_resource_reference(&drawable->textures[statt], NULL); 715 } 716 } 717 718 /* For DRI2, we may get the same buffers again from the server. 719 * To prevent useless imports of gem names, drawable->old* is used 720 * to bypass the import if we get the same buffers. This doesn't apply 721 * to DRI3/Wayland, users of image.loader, since the buffer is managed 722 * by the client (no import), and the back buffer is going to change 723 * at every redraw. 724 */ 725 if (!image) { 726 drawable->old_num = num_buffers; 727 drawable->old_w = dri_drawable->w; 728 drawable->old_h = dri_drawable->h; 729 memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers); 730 } 731} 732 733static bool 734dri2_flush_frontbuffer(struct dri_context *ctx, 735 struct dri_drawable *drawable, 736 enum st_attachment_type statt) 737{ 738 __DRIdrawable *dri_drawable = drawable->dPriv; 739 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; 740 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; 741 const __DRImutableRenderBufferLoaderExtension *shared_buffer_loader = 742 drawable->sPriv->mutableRenderBuffer.loader; 743 struct pipe_context *pipe = ctx->st->pipe; 744 struct pipe_fence_handle *fence = NULL; 745 int fence_fd = -1; 746 747 /* We need to flush for front buffer rendering when either we're using the 748 * front buffer at the GL API level, or when EGL_KHR_mutable_render_buffer 749 * has redirected GL_BACK to the front buffer. 750 */ 751 if (statt != ST_ATTACHMENT_FRONT_LEFT && 752 (!ctx->is_shared_buffer_bound || statt != ST_ATTACHMENT_BACK_LEFT)) 753 return false; 754 755 if (drawable->stvis.samples > 1) { 756 /* Resolve the buffer used for front rendering. */ 757 dri_pipe_blit(ctx->st->pipe, drawable->textures[statt], 758 drawable->msaa_textures[statt]); 759 } 760 761 if (drawable->textures[statt]) { 762 pipe->flush_resource(pipe, drawable->textures[statt]); 763 } 764 765 if (ctx->is_shared_buffer_bound) { 766 /* is_shared_buffer_bound should only be true with image extension: */ 767 assert(image); 768 pipe->flush(pipe, &fence, PIPE_FLUSH_FENCE_FD); 769 } else { 770 pipe->flush(pipe, NULL, 0); 771 } 772 773 if (image) { 774 image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); 775 if (ctx->is_shared_buffer_bound) { 776 if (fence) 777 fence_fd = pipe->screen->fence_get_fd(pipe->screen, fence); 778 779 shared_buffer_loader->displaySharedBuffer(dri_drawable, fence_fd, 780 dri_drawable->loaderPrivate); 781 782 pipe->screen->fence_reference(pipe->screen, &fence, NULL); 783 } 784 } 785 else if (loader->flushFrontBuffer) { 786 loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); 787 } 788 789 return true; 790} 791 792/** 793 * The struct dri_drawable flush_swapbuffers callback 794 */ 795static void 796dri2_flush_swapbuffers(struct dri_context *ctx, 797 struct dri_drawable *drawable) 798{ 799 __DRIdrawable *dri_drawable = drawable->dPriv; 800 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; 801 802 if (image && image->base.version >= 3 && image->flushSwapBuffers) { 803 image->flushSwapBuffers(dri_drawable, dri_drawable->loaderPrivate); 804 } 805} 806 807static void 808dri2_update_tex_buffer(struct dri_drawable *drawable, 809 struct dri_context *ctx, 810 struct pipe_resource *res) 811{ 812 /* no-op */ 813} 814 815static const struct dri2_format_mapping r8_g8b8_mapping = { 816 DRM_FORMAT_NV12, 817 __DRI_IMAGE_FORMAT_NONE, 818 __DRI_IMAGE_COMPONENTS_Y_UV, 819 PIPE_FORMAT_R8_G8B8_420_UNORM, 820 2, 821 { { 0, 0, 0, __DRI_IMAGE_FORMAT_R8 }, 822 { 1, 1, 1, __DRI_IMAGE_FORMAT_GR88 } } 823}; 824 825static const struct dri2_format_mapping r8g8_r8b8_mapping = { 826 DRM_FORMAT_YUYV, 827 __DRI_IMAGE_FORMAT_NONE, 828 __DRI_IMAGE_COMPONENTS_Y_XUXV, 829 PIPE_FORMAT_R8G8_R8B8_UNORM, 2, 830 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 }, 831 { 0, 1, 0, __DRI_IMAGE_FORMAT_ARGB8888 } } 832}; 833 834static const struct dri2_format_mapping g8r8_b8r8_mapping = { 835 DRM_FORMAT_UYVY, 836 __DRI_IMAGE_FORMAT_NONE, 837 __DRI_IMAGE_COMPONENTS_Y_XUXV, 838 PIPE_FORMAT_G8R8_B8R8_UNORM, 2, 839 { { 0, 0, 0, __DRI_IMAGE_FORMAT_GR88 }, 840 { 0, 1, 0, __DRI_IMAGE_FORMAT_ABGR8888 } } 841}; 842 843static __DRIimage * 844dri2_create_image_from_winsys(__DRIscreen *_screen, 845 int width, int height, const struct dri2_format_mapping *map, 846 int num_handles, struct winsys_handle *whandle, 847 unsigned bind, 848 void *loaderPrivate) 849{ 850 struct dri_screen *screen = dri_screen(_screen); 851 struct pipe_screen *pscreen = screen->base.screen; 852 __DRIimage *img; 853 struct pipe_resource templ; 854 unsigned tex_usage = 0; 855 int i; 856 bool use_lowered = false; 857 const unsigned format_planes = util_format_get_num_planes(map->pipe_format); 858 859 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0, 860 PIPE_BIND_RENDER_TARGET)) 861 tex_usage |= PIPE_BIND_RENDER_TARGET; 862 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 0, 0, 863 PIPE_BIND_SAMPLER_VIEW)) 864 tex_usage |= PIPE_BIND_SAMPLER_VIEW; 865 866 /* For NV12, see if we have support for sampling r8_b8g8 */ 867 if (!tex_usage && map->pipe_format == PIPE_FORMAT_NV12 && 868 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8_G8B8_420_UNORM, 869 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { 870 map = &r8_g8b8_mapping; 871 tex_usage |= PIPE_BIND_SAMPLER_VIEW; 872 } 873 874 /* If the hardware supports R8G8_R8B8 style subsampled RGB formats, these 875 * can be used for YUYV and UYVY formats. 876 */ 877 if (!tex_usage && map->pipe_format == PIPE_FORMAT_YUYV && 878 pscreen->is_format_supported(pscreen, PIPE_FORMAT_R8G8_R8B8_UNORM, 879 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { 880 map = &r8g8_r8b8_mapping; 881 tex_usage |= PIPE_BIND_SAMPLER_VIEW; 882 } 883 884 if (!tex_usage && map->pipe_format == PIPE_FORMAT_UYVY && 885 pscreen->is_format_supported(pscreen, PIPE_FORMAT_G8R8_B8R8_UNORM, 886 screen->target, 0, 0, PIPE_BIND_SAMPLER_VIEW)) { 887 map = &g8r8_b8r8_mapping; 888 tex_usage |= PIPE_BIND_SAMPLER_VIEW; 889 } 890 891 if (!tex_usage && util_format_is_yuv(map->pipe_format)) { 892 /* YUV format sampling can be emulated by the GL gallium frontend by 893 * using multiple samplers of varying formats. 894 * If no tex_usage is set and we detect a YUV format, 895 * test for support of all planes' sampler formats and 896 * add sampler view usage. 897 */ 898 use_lowered = true; 899 if (dri2_yuv_dma_buf_supported(screen, map)) 900 tex_usage |= PIPE_BIND_SAMPLER_VIEW; 901 } 902 903 if (!tex_usage) 904 return NULL; 905 906 img = CALLOC_STRUCT(__DRIimageRec); 907 if (!img) 908 return NULL; 909 910 memset(&templ, 0, sizeof(templ)); 911 templ.bind = tex_usage | bind; 912 templ.target = screen->target; 913 templ.last_level = 0; 914 templ.depth0 = 1; 915 templ.array_size = 1; 916 templ.width0 = width; 917 templ.height0 = height; 918 919 for (i = num_handles - 1; i >= format_planes; i--) { 920 struct pipe_resource *tex; 921 922 templ.next = img->texture; 923 924 tex = pscreen->resource_from_handle(pscreen, &templ, &whandle[i], 925 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 926 if (!tex) { 927 pipe_resource_reference(&img->texture, NULL); 928 FREE(img); 929 return NULL; 930 } 931 932 img->texture = tex; 933 } 934 935 for (i = (use_lowered ? map->nplanes : format_planes) - 1; i >= 0; i--) { 936 struct pipe_resource *tex; 937 938 templ.next = img->texture; 939 templ.width0 = width >> map->planes[i].width_shift; 940 templ.height0 = height >> map->planes[i].height_shift; 941 if (use_lowered) 942 templ.format = dri2_get_pipe_format_for_dri_format(map->planes[i].dri_format); 943 else 944 templ.format = map->pipe_format; 945 assert(templ.format != PIPE_FORMAT_NONE); 946 947 tex = pscreen->resource_from_handle(pscreen, 948 &templ, &whandle[use_lowered ? map->planes[i].buffer_index : i], 949 PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE); 950 if (!tex) { 951 pipe_resource_reference(&img->texture, NULL); 952 FREE(img); 953 return NULL; 954 } 955 956 /* Reject image creation if there's an inconsistency between 957 * content protection status of tex and img. 958 */ 959 const struct driOptionCache *optionCache = &screen->dev->option_cache; 960 if (!driQueryOptionb(optionCache, "disable_protected_content_check") && 961 (tex->bind & PIPE_BIND_PROTECTED) != (bind & PIPE_BIND_PROTECTED)) { 962 pipe_resource_reference(&img->texture, NULL); 963 pipe_resource_reference(&tex, NULL); 964 FREE(img); 965 return NULL; 966 } 967 968 img->texture = tex; 969 } 970 971 img->level = 0; 972 img->layer = 0; 973 img->use = 0; 974 img->in_fence_fd = -1; 975 img->loader_private = loaderPrivate; 976 img->sPriv = _screen; 977 978 return img; 979} 980 981static __DRIimage * 982dri2_create_image_from_name(__DRIscreen *_screen, 983 int width, int height, int format, 984 int name, int pitch, void *loaderPrivate) 985{ 986 const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); 987 struct winsys_handle whandle; 988 __DRIimage *img; 989 990 if (!map) 991 return NULL; 992 993 memset(&whandle, 0, sizeof(whandle)); 994 whandle.type = WINSYS_HANDLE_TYPE_SHARED; 995 whandle.handle = name; 996 whandle.format = map->pipe_format; 997 whandle.modifier = DRM_FORMAT_MOD_INVALID; 998 999 whandle.stride = pitch * util_format_get_blocksize(map->pipe_format); 1000 1001 img = dri2_create_image_from_winsys(_screen, width, height, map, 1002 1, &whandle, 0, loaderPrivate); 1003 1004 if (!img) 1005 return NULL; 1006 1007 img->dri_components = map->dri_components; 1008 img->dri_fourcc = map->dri_fourcc; 1009 img->dri_format = map->dri_format; 1010 1011 return img; 1012} 1013 1014static unsigned 1015dri2_get_modifier_num_planes(__DRIscreen *_screen, 1016 uint64_t modifier, int fourcc) 1017{ 1018 struct pipe_screen *pscreen = dri_screen(_screen)->base.screen; 1019 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); 1020 1021 if (!map) 1022 return 0; 1023 1024 switch (modifier) { 1025 case DRM_FORMAT_MOD_LINEAR: 1026 /* DRM_FORMAT_MOD_NONE is the same as LINEAR */ 1027 case DRM_FORMAT_MOD_INVALID: 1028 return util_format_get_num_planes(map->pipe_format); 1029 default: 1030 if (!pscreen->is_dmabuf_modifier_supported || 1031 !pscreen->is_dmabuf_modifier_supported(pscreen, modifier, 1032 map->pipe_format, NULL)) { 1033 return 0; 1034 } 1035 1036 if (pscreen->get_dmabuf_modifier_planes) { 1037 return pscreen->get_dmabuf_modifier_planes(pscreen, modifier, 1038 map->pipe_format); 1039 } 1040 1041 return map->nplanes; 1042 } 1043} 1044 1045static __DRIimage * 1046dri2_create_image_from_fd(__DRIscreen *_screen, 1047 int width, int height, int fourcc, 1048 uint64_t modifier, int *fds, int num_fds, 1049 int *strides, int *offsets, 1050 unsigned bind, unsigned *error, void *loaderPrivate) 1051{ 1052 struct winsys_handle whandles[4]; 1053 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); 1054 __DRIimage *img = NULL; 1055 unsigned err = __DRI_IMAGE_ERROR_SUCCESS; 1056 int i; 1057 const int expected_num_fds = dri2_get_modifier_num_planes(_screen, modifier, fourcc); 1058 1059 if (!map || expected_num_fds == 0) { 1060 err = __DRI_IMAGE_ERROR_BAD_MATCH; 1061 goto exit; 1062 } 1063 1064 if (num_fds != expected_num_fds) { 1065 err = __DRI_IMAGE_ERROR_BAD_MATCH; 1066 goto exit; 1067 } 1068 1069 memset(whandles, 0, sizeof(whandles)); 1070 1071 for (i = 0; i < num_fds; i++) { 1072 if (fds[i] < 0) { 1073 err = __DRI_IMAGE_ERROR_BAD_ALLOC; 1074 goto exit; 1075 } 1076 1077 whandles[i].type = WINSYS_HANDLE_TYPE_FD; 1078 whandles[i].handle = (unsigned)fds[i]; 1079 whandles[i].stride = (unsigned)strides[i]; 1080 whandles[i].offset = (unsigned)offsets[i]; 1081 whandles[i].format = map->pipe_format; 1082 whandles[i].modifier = modifier; 1083 whandles[i].plane = i; 1084 } 1085 1086 img = dri2_create_image_from_winsys(_screen, width, height, map, 1087 num_fds, whandles, bind, 1088 loaderPrivate); 1089 if(img == NULL) { 1090 err = __DRI_IMAGE_ERROR_BAD_ALLOC; 1091 goto exit; 1092 } 1093 1094 img->dri_components = map->dri_components; 1095 img->dri_fourcc = fourcc; 1096 img->dri_format = map->dri_format; 1097 img->imported_dmabuf = TRUE; 1098 1099exit: 1100 if (error) 1101 *error = err; 1102 1103 return img; 1104} 1105 1106static __DRIimage * 1107dri2_create_image_common(__DRIscreen *_screen, 1108 int width, int height, 1109 int format, unsigned int use, 1110 const uint64_t *modifiers, 1111 const unsigned count, 1112 void *loaderPrivate) 1113{ 1114 const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); 1115 struct dri_screen *screen = dri_screen(_screen); 1116 struct pipe_screen *pscreen = screen->base.screen; 1117 __DRIimage *img; 1118 struct pipe_resource templ; 1119 unsigned tex_usage = 0; 1120 1121 if (!map) 1122 return NULL; 1123 1124 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 1125 0, 0, PIPE_BIND_RENDER_TARGET)) 1126 tex_usage |= PIPE_BIND_RENDER_TARGET; 1127 if (pscreen->is_format_supported(pscreen, map->pipe_format, screen->target, 1128 0, 0, PIPE_BIND_SAMPLER_VIEW)) 1129 tex_usage |= PIPE_BIND_SAMPLER_VIEW; 1130 1131 if (!tex_usage) 1132 return NULL; 1133 1134 if (use & __DRI_IMAGE_USE_SCANOUT) 1135 tex_usage |= PIPE_BIND_SCANOUT; 1136 if (use & __DRI_IMAGE_USE_SHARE) 1137 tex_usage |= PIPE_BIND_SHARED; 1138 if (use & __DRI_IMAGE_USE_LINEAR) 1139 tex_usage |= PIPE_BIND_LINEAR; 1140 if (use & __DRI_IMAGE_USE_CURSOR) { 1141 if (width != 64 || height != 64) 1142 return NULL; 1143 tex_usage |= PIPE_BIND_CURSOR; 1144 } 1145 if (use & __DRI_IMAGE_USE_PROTECTED) 1146 tex_usage |= PIPE_BIND_PROTECTED; 1147 if (use & __DRI_IMAGE_USE_PRIME_BUFFER) 1148 tex_usage |= PIPE_BIND_PRIME_BLIT_DST; 1149 1150 img = CALLOC_STRUCT(__DRIimageRec); 1151 if (!img) 1152 return NULL; 1153 1154 memset(&templ, 0, sizeof(templ)); 1155 templ.bind = tex_usage; 1156 templ.format = map->pipe_format; 1157 templ.target = PIPE_TEXTURE_2D; 1158 templ.last_level = 0; 1159 templ.width0 = width; 1160 templ.height0 = height; 1161 templ.depth0 = 1; 1162 templ.array_size = 1; 1163 1164 if (modifiers) 1165 img->texture = 1166 screen->base.screen 1167 ->resource_create_with_modifiers(screen->base.screen, 1168 &templ, 1169 modifiers, 1170 count); 1171 else 1172 img->texture = 1173 screen->base.screen->resource_create(screen->base.screen, &templ); 1174 if (!img->texture) { 1175 FREE(img); 1176 return NULL; 1177 } 1178 1179 img->level = 0; 1180 img->layer = 0; 1181 img->dri_format = format; 1182 img->dri_fourcc = map->dri_fourcc; 1183 img->dri_components = 0; 1184 img->use = use; 1185 img->in_fence_fd = -1; 1186 1187 img->loader_private = loaderPrivate; 1188 img->sPriv = _screen; 1189 return img; 1190} 1191 1192static __DRIimage * 1193dri2_create_image(__DRIscreen *_screen, 1194 int width, int height, int format, 1195 unsigned int use, void *loaderPrivate) 1196{ 1197 return dri2_create_image_common(_screen, width, height, format, use, 1198 NULL /* modifiers */, 0 /* count */, 1199 loaderPrivate); 1200} 1201 1202static __DRIimage * 1203dri2_create_image_with_modifiers(__DRIscreen *dri_screen, 1204 int width, int height, int format, 1205 const uint64_t *modifiers, 1206 const unsigned count, 1207 void *loaderPrivate) 1208{ 1209 return dri2_create_image_common(dri_screen, width, height, format, 1210 __DRI_IMAGE_USE_SHARE, modifiers, count, 1211 loaderPrivate); 1212} 1213 1214static __DRIimage * 1215dri2_create_image_with_modifiers2(__DRIscreen *dri_screen, 1216 int width, int height, int format, 1217 const uint64_t *modifiers, 1218 const unsigned count, unsigned int use, 1219 void *loaderPrivate) 1220{ 1221 return dri2_create_image_common(dri_screen, width, height, format, use, 1222 modifiers, count, loaderPrivate); 1223} 1224 1225static bool 1226dri2_query_image_common(__DRIimage *image, int attrib, int *value) 1227{ 1228 switch (attrib) { 1229 case __DRI_IMAGE_ATTRIB_FORMAT: 1230 *value = image->dri_format; 1231 return true; 1232 case __DRI_IMAGE_ATTRIB_WIDTH: 1233 *value = image->texture->width0; 1234 return true; 1235 case __DRI_IMAGE_ATTRIB_HEIGHT: 1236 *value = image->texture->height0; 1237 return true; 1238 case __DRI_IMAGE_ATTRIB_COMPONENTS: 1239 if (image->dri_components == 0) 1240 return false; 1241 *value = image->dri_components; 1242 return true; 1243 case __DRI_IMAGE_ATTRIB_FOURCC: 1244 if (image->dri_fourcc) { 1245 *value = image->dri_fourcc; 1246 } else { 1247 const struct dri2_format_mapping *map; 1248 1249 map = dri2_get_mapping_by_format(image->dri_format); 1250 if (!map) 1251 return false; 1252 1253 *value = map->dri_fourcc; 1254 } 1255 return true; 1256 default: 1257 return false; 1258 } 1259} 1260 1261static bool 1262dri2_query_image_by_resource_handle(__DRIimage *image, int attrib, int *value) 1263{ 1264 struct pipe_screen *pscreen = image->texture->screen; 1265 struct winsys_handle whandle; 1266 struct pipe_resource *tex; 1267 unsigned usage; 1268 memset(&whandle, 0, sizeof(whandle)); 1269 whandle.plane = image->plane; 1270 int i; 1271 1272 switch (attrib) { 1273 case __DRI_IMAGE_ATTRIB_STRIDE: 1274 case __DRI_IMAGE_ATTRIB_OFFSET: 1275 case __DRI_IMAGE_ATTRIB_HANDLE: 1276 whandle.type = WINSYS_HANDLE_TYPE_KMS; 1277 break; 1278 case __DRI_IMAGE_ATTRIB_NAME: 1279 whandle.type = WINSYS_HANDLE_TYPE_SHARED; 1280 break; 1281 case __DRI_IMAGE_ATTRIB_FD: 1282 whandle.type = WINSYS_HANDLE_TYPE_FD; 1283 break; 1284 case __DRI_IMAGE_ATTRIB_NUM_PLANES: 1285 for (i = 0, tex = image->texture; tex; tex = tex->next) 1286 i++; 1287 *value = i; 1288 return true; 1289 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: 1290 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: 1291 whandle.type = WINSYS_HANDLE_TYPE_KMS; 1292 whandle.modifier = DRM_FORMAT_MOD_INVALID; 1293 break; 1294 default: 1295 return false; 1296 } 1297 1298 usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; 1299 1300 if (image->use & __DRI_IMAGE_USE_BACKBUFFER) 1301 usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH; 1302 1303 if (!pscreen->resource_get_handle(pscreen, NULL, image->texture, 1304 &whandle, usage)) 1305 return false; 1306 1307 switch (attrib) { 1308 case __DRI_IMAGE_ATTRIB_STRIDE: 1309 *value = whandle.stride; 1310 return true; 1311 case __DRI_IMAGE_ATTRIB_OFFSET: 1312 *value = whandle.offset; 1313 return true; 1314 case __DRI_IMAGE_ATTRIB_HANDLE: 1315 case __DRI_IMAGE_ATTRIB_NAME: 1316 case __DRI_IMAGE_ATTRIB_FD: 1317 *value = whandle.handle; 1318 return true; 1319 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: 1320 if (whandle.modifier == DRM_FORMAT_MOD_INVALID) 1321 return false; 1322 *value = (whandle.modifier >> 32) & 0xffffffff; 1323 return true; 1324 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: 1325 if (whandle.modifier == DRM_FORMAT_MOD_INVALID) 1326 return false; 1327 *value = whandle.modifier & 0xffffffff; 1328 return true; 1329 default: 1330 return false; 1331 } 1332} 1333 1334static bool 1335dri2_resource_get_param(__DRIimage *image, enum pipe_resource_param param, 1336 unsigned handle_usage, uint64_t *value) 1337{ 1338 struct pipe_screen *pscreen = image->texture->screen; 1339 if (!pscreen->resource_get_param) 1340 return false; 1341 1342 if (image->use & __DRI_IMAGE_USE_BACKBUFFER) 1343 handle_usage |= PIPE_HANDLE_USAGE_EXPLICIT_FLUSH; 1344 1345 return pscreen->resource_get_param(pscreen, NULL, image->texture, 1346 image->plane, 0, 0, param, handle_usage, 1347 value); 1348} 1349 1350static bool 1351dri2_query_image_by_resource_param(__DRIimage *image, int attrib, int *value) 1352{ 1353 enum pipe_resource_param param; 1354 uint64_t res_param; 1355 unsigned handle_usage; 1356 1357 if (!image->texture->screen->resource_get_param) 1358 return false; 1359 1360 switch (attrib) { 1361 case __DRI_IMAGE_ATTRIB_STRIDE: 1362 param = PIPE_RESOURCE_PARAM_STRIDE; 1363 break; 1364 case __DRI_IMAGE_ATTRIB_OFFSET: 1365 param = PIPE_RESOURCE_PARAM_OFFSET; 1366 break; 1367 case __DRI_IMAGE_ATTRIB_NUM_PLANES: 1368 param = PIPE_RESOURCE_PARAM_NPLANES; 1369 break; 1370 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: 1371 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: 1372 param = PIPE_RESOURCE_PARAM_MODIFIER; 1373 break; 1374 case __DRI_IMAGE_ATTRIB_HANDLE: 1375 param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_KMS; 1376 break; 1377 case __DRI_IMAGE_ATTRIB_NAME: 1378 param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_SHARED; 1379 break; 1380 case __DRI_IMAGE_ATTRIB_FD: 1381 param = PIPE_RESOURCE_PARAM_HANDLE_TYPE_FD; 1382 break; 1383 default: 1384 return false; 1385 } 1386 1387 handle_usage = PIPE_HANDLE_USAGE_FRAMEBUFFER_WRITE; 1388 1389 if (!dri2_resource_get_param(image, param, handle_usage, &res_param)) 1390 return false; 1391 1392 switch (attrib) { 1393 case __DRI_IMAGE_ATTRIB_STRIDE: 1394 case __DRI_IMAGE_ATTRIB_OFFSET: 1395 case __DRI_IMAGE_ATTRIB_NUM_PLANES: 1396 if (res_param > INT_MAX) 1397 return false; 1398 *value = (int)res_param; 1399 return true; 1400 case __DRI_IMAGE_ATTRIB_HANDLE: 1401 case __DRI_IMAGE_ATTRIB_NAME: 1402 case __DRI_IMAGE_ATTRIB_FD: 1403 if (res_param > UINT_MAX) 1404 return false; 1405 *value = (int)res_param; 1406 return true; 1407 case __DRI_IMAGE_ATTRIB_MODIFIER_UPPER: 1408 if (res_param == DRM_FORMAT_MOD_INVALID) 1409 return false; 1410 *value = (res_param >> 32) & 0xffffffff; 1411 return true; 1412 case __DRI_IMAGE_ATTRIB_MODIFIER_LOWER: 1413 if (res_param == DRM_FORMAT_MOD_INVALID) 1414 return false; 1415 *value = res_param & 0xffffffff; 1416 return true; 1417 default: 1418 return false; 1419 } 1420} 1421 1422static GLboolean 1423dri2_query_image(__DRIimage *image, int attrib, int *value) 1424{ 1425 if (dri2_query_image_common(image, attrib, value)) 1426 return GL_TRUE; 1427 else if (dri2_query_image_by_resource_param(image, attrib, value)) 1428 return GL_TRUE; 1429 else if (dri2_query_image_by_resource_handle(image, attrib, value)) 1430 return GL_TRUE; 1431 else 1432 return GL_FALSE; 1433} 1434 1435static __DRIimage * 1436dri2_dup_image(__DRIimage *image, void *loaderPrivate) 1437{ 1438 __DRIimage *img; 1439 1440 img = CALLOC_STRUCT(__DRIimageRec); 1441 if (!img) 1442 return NULL; 1443 1444 img->texture = NULL; 1445 pipe_resource_reference(&img->texture, image->texture); 1446 img->level = image->level; 1447 img->layer = image->layer; 1448 img->dri_format = image->dri_format; 1449 img->internal_format = image->internal_format; 1450 /* This should be 0 for sub images, but dup is also used for base images. */ 1451 img->dri_components = image->dri_components; 1452 img->use = image->use; 1453 img->in_fence_fd = (image->in_fence_fd > 0) ? 1454 os_dupfd_cloexec(image->in_fence_fd) : -1; 1455 img->loader_private = loaderPrivate; 1456 img->sPriv = image->sPriv; 1457 1458 return img; 1459} 1460 1461static GLboolean 1462dri2_validate_usage(__DRIimage *image, unsigned int use) 1463{ 1464 if (!image || !image->texture) 1465 return false; 1466 1467 struct pipe_screen *screen = image->texture->screen; 1468 if (!screen->check_resource_capability) 1469 return true; 1470 1471 /* We don't want to check these: 1472 * __DRI_IMAGE_USE_SHARE (all images are shareable) 1473 * __DRI_IMAGE_USE_BACKBUFFER (all images support this) 1474 */ 1475 unsigned bind = 0; 1476 if (use & __DRI_IMAGE_USE_SCANOUT) 1477 bind |= PIPE_BIND_SCANOUT; 1478 if (use & __DRI_IMAGE_USE_LINEAR) 1479 bind |= PIPE_BIND_LINEAR; 1480 if (use & __DRI_IMAGE_USE_CURSOR) 1481 bind |= PIPE_BIND_CURSOR; 1482 1483 if (!bind) 1484 return true; 1485 1486 return screen->check_resource_capability(screen, image->texture, bind); 1487} 1488 1489static __DRIimage * 1490dri2_from_names(__DRIscreen *screen, int width, int height, int format, 1491 int *names, int num_names, int *strides, int *offsets, 1492 void *loaderPrivate) 1493{ 1494 const struct dri2_format_mapping *map = dri2_get_mapping_by_format(format); 1495 __DRIimage *img; 1496 struct winsys_handle whandle; 1497 1498 if (!map) 1499 return NULL; 1500 1501 if (num_names != 1) 1502 return NULL; 1503 1504 memset(&whandle, 0, sizeof(whandle)); 1505 whandle.type = WINSYS_HANDLE_TYPE_SHARED; 1506 whandle.handle = names[0]; 1507 whandle.stride = strides[0]; 1508 whandle.offset = offsets[0]; 1509 whandle.format = map->pipe_format; 1510 whandle.modifier = DRM_FORMAT_MOD_INVALID; 1511 1512 img = dri2_create_image_from_winsys(screen, width, height, map, 1513 1, &whandle, 0, loaderPrivate); 1514 if (img == NULL) 1515 return NULL; 1516 1517 img->dri_components = map->dri_components; 1518 img->dri_fourcc = map->dri_fourcc; 1519 img->dri_format = map->pipe_format; 1520 1521 return img; 1522} 1523 1524static __DRIimage * 1525dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) 1526{ 1527 __DRIimage *img; 1528 1529 if (plane < 0) { 1530 return NULL; 1531 } else if (plane > 0) { 1532 uint64_t planes; 1533 if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_NPLANES, 0, 1534 &planes) || 1535 plane >= planes) { 1536 return NULL; 1537 } 1538 } 1539 1540 if (image->dri_components == 0) { 1541 uint64_t modifier; 1542 if (!dri2_resource_get_param(image, PIPE_RESOURCE_PARAM_MODIFIER, 0, 1543 &modifier) || 1544 modifier == DRM_FORMAT_MOD_INVALID) { 1545 return NULL; 1546 } 1547 } 1548 1549 img = dri2_dup_image(image, loaderPrivate); 1550 if (img == NULL) 1551 return NULL; 1552 1553 if (img->texture->screen->resource_changed) 1554 img->texture->screen->resource_changed(img->texture->screen, 1555 img->texture); 1556 1557 /* set this to 0 for sub images. */ 1558 img->dri_components = 0; 1559 img->plane = plane; 1560 return img; 1561} 1562 1563static __DRIimage * 1564dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc, 1565 int *fds, int num_fds, int *strides, int *offsets, 1566 void *loaderPrivate) 1567{ 1568 return dri2_create_image_from_fd(screen, width, height, fourcc, 1569 DRM_FORMAT_MOD_INVALID, fds, num_fds, 1570 strides, offsets, 0, NULL, loaderPrivate); 1571} 1572 1573static __DRIimage * 1574dri2_from_fds2(__DRIscreen *screen, int width, int height, int fourcc, 1575 int *fds, int num_fds, uint32_t flags, int *strides, 1576 int *offsets, void *loaderPrivate) 1577{ 1578 unsigned bind = 0; 1579 if (flags & __DRI_IMAGE_PROTECTED_CONTENT_FLAG) 1580 bind |= PIPE_BIND_PROTECTED; 1581 if (flags & __DRI_IMAGE_PRIME_LINEAR_BUFFER) 1582 bind |= PIPE_BIND_PRIME_BLIT_DST; 1583 1584 return dri2_create_image_from_fd(screen, width, height, fourcc, 1585 DRM_FORMAT_MOD_INVALID, fds, num_fds, 1586 strides, offsets, bind, NULL, loaderPrivate); 1587} 1588 1589static boolean 1590dri2_query_dma_buf_modifiers(__DRIscreen *_screen, int fourcc, int max, 1591 uint64_t *modifiers, unsigned int *external_only, 1592 int *count) 1593{ 1594 struct dri_screen *screen = dri_screen(_screen); 1595 struct pipe_screen *pscreen = screen->base.screen; 1596 const struct dri2_format_mapping *map = dri2_get_mapping_by_fourcc(fourcc); 1597 enum pipe_format format; 1598 1599 if (!map) 1600 return false; 1601 1602 format = map->pipe_format; 1603 1604 bool native_sampling = pscreen->is_format_supported(pscreen, format, screen->target, 0, 0, 1605 PIPE_BIND_SAMPLER_VIEW); 1606 if (pscreen->is_format_supported(pscreen, format, screen->target, 0, 0, 1607 PIPE_BIND_RENDER_TARGET) || 1608 native_sampling || 1609 dri2_yuv_dma_buf_supported(screen, map)) { 1610 if (pscreen->query_dmabuf_modifiers != NULL) { 1611 pscreen->query_dmabuf_modifiers(pscreen, format, max, modifiers, 1612 external_only, count); 1613 if (!native_sampling && external_only) { 1614 /* To support it using YUV lowering, we need it to be samplerExternalOES. 1615 */ 1616 for (int i = 0; i < *count; i++) 1617 external_only[i] = true; 1618 } 1619 } else { 1620 *count = 0; 1621 } 1622 return true; 1623 } 1624 return false; 1625} 1626 1627static boolean 1628dri2_query_dma_buf_format_modifier_attribs(__DRIscreen *_screen, 1629 uint32_t fourcc, uint64_t modifier, 1630 int attrib, uint64_t *value) 1631{ 1632 struct dri_screen *screen = dri_screen(_screen); 1633 struct pipe_screen *pscreen = screen->base.screen; 1634 1635 if (!pscreen->query_dmabuf_modifiers) 1636 return false; 1637 1638 switch (attrib) { 1639 case __DRI_IMAGE_FORMAT_MODIFIER_ATTRIB_PLANE_COUNT: { 1640 uint64_t mod_planes = dri2_get_modifier_num_planes(_screen, modifier, 1641 fourcc); 1642 if (mod_planes > 0) 1643 *value = mod_planes; 1644 return mod_planes > 0; 1645 } 1646 default: 1647 return false; 1648 } 1649} 1650 1651static __DRIimage * 1652dri2_from_dma_bufs(__DRIscreen *screen, 1653 int width, int height, int fourcc, 1654 int *fds, int num_fds, 1655 int *strides, int *offsets, 1656 enum __DRIYUVColorSpace yuv_color_space, 1657 enum __DRISampleRange sample_range, 1658 enum __DRIChromaSiting horizontal_siting, 1659 enum __DRIChromaSiting vertical_siting, 1660 unsigned *error, 1661 void *loaderPrivate) 1662{ 1663 __DRIimage *img; 1664 1665 img = dri2_create_image_from_fd(screen, width, height, fourcc, 1666 DRM_FORMAT_MOD_INVALID, fds, num_fds, 1667 strides, offsets, 0, error, loaderPrivate); 1668 if (img == NULL) 1669 return NULL; 1670 1671 img->yuv_color_space = yuv_color_space; 1672 img->sample_range = sample_range; 1673 img->horizontal_siting = horizontal_siting; 1674 img->vertical_siting = vertical_siting; 1675 1676 *error = __DRI_IMAGE_ERROR_SUCCESS; 1677 return img; 1678} 1679 1680static __DRIimage * 1681dri2_from_dma_bufs2(__DRIscreen *screen, 1682 int width, int height, int fourcc, 1683 uint64_t modifier, int *fds, int num_fds, 1684 int *strides, int *offsets, 1685 enum __DRIYUVColorSpace yuv_color_space, 1686 enum __DRISampleRange sample_range, 1687 enum __DRIChromaSiting horizontal_siting, 1688 enum __DRIChromaSiting vertical_siting, 1689 unsigned *error, 1690 void *loaderPrivate) 1691{ 1692 __DRIimage *img; 1693 1694 img = dri2_create_image_from_fd(screen, width, height, fourcc, 1695 modifier, fds, num_fds, strides, offsets, 1696 0, error, loaderPrivate); 1697 if (img == NULL) 1698 return NULL; 1699 1700 img->yuv_color_space = yuv_color_space; 1701 img->sample_range = sample_range; 1702 img->horizontal_siting = horizontal_siting; 1703 img->vertical_siting = vertical_siting; 1704 1705 *error = __DRI_IMAGE_ERROR_SUCCESS; 1706 return img; 1707} 1708 1709static __DRIimage * 1710dri2_from_dma_bufs3(__DRIscreen *screen, 1711 int width, int height, int fourcc, 1712 uint64_t modifier, int *fds, int num_fds, 1713 int *strides, int *offsets, 1714 enum __DRIYUVColorSpace yuv_color_space, 1715 enum __DRISampleRange sample_range, 1716 enum __DRIChromaSiting horizontal_siting, 1717 enum __DRIChromaSiting vertical_siting, 1718 uint32_t flags, 1719 unsigned *error, 1720 void *loaderPrivate) 1721{ 1722 __DRIimage *img; 1723 1724 img = dri2_create_image_from_fd(screen, width, height, fourcc, 1725 modifier, fds, num_fds, strides, offsets, 1726 (flags & __DRI_IMAGE_PROTECTED_CONTENT_FLAG) ? 1727 PIPE_BIND_PROTECTED : 0, 1728 error, loaderPrivate); 1729 if (img == NULL) 1730 return NULL; 1731 1732 img->yuv_color_space = yuv_color_space; 1733 img->sample_range = sample_range; 1734 img->horizontal_siting = horizontal_siting; 1735 img->vertical_siting = vertical_siting; 1736 1737 *error = __DRI_IMAGE_ERROR_SUCCESS; 1738 return img; 1739} 1740 1741static void 1742dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src, 1743 int dstx0, int dsty0, int dstwidth, int dstheight, 1744 int srcx0, int srcy0, int srcwidth, int srcheight, 1745 int flush_flag) 1746{ 1747 struct dri_context *ctx = dri_context(context); 1748 struct pipe_context *pipe = ctx->st->pipe; 1749 struct pipe_screen *screen; 1750 struct pipe_fence_handle *fence; 1751 struct pipe_blit_info blit; 1752 1753 if (!dst || !src) 1754 return; 1755 1756 handle_in_fence(context, dst); 1757 1758 memset(&blit, 0, sizeof(blit)); 1759 blit.dst.resource = dst->texture; 1760 blit.dst.box.x = dstx0; 1761 blit.dst.box.y = dsty0; 1762 blit.dst.box.width = dstwidth; 1763 blit.dst.box.height = dstheight; 1764 blit.dst.box.depth = 1; 1765 blit.dst.format = dst->texture->format; 1766 blit.src.resource = src->texture; 1767 blit.src.box.x = srcx0; 1768 blit.src.box.y = srcy0; 1769 blit.src.box.width = srcwidth; 1770 blit.src.box.height = srcheight; 1771 blit.src.box.depth = 1; 1772 blit.src.format = src->texture->format; 1773 blit.mask = PIPE_MASK_RGBA; 1774 blit.filter = PIPE_TEX_FILTER_NEAREST; 1775 1776 pipe->blit(pipe, &blit); 1777 1778 if (flush_flag == __BLIT_FLAG_FLUSH) { 1779 pipe->flush_resource(pipe, dst->texture); 1780 ctx->st->flush(ctx->st, 0, NULL, NULL, NULL); 1781 } else if (flush_flag == __BLIT_FLAG_FINISH) { 1782 screen = dri_screen(ctx->sPriv)->base.screen; 1783 pipe->flush_resource(pipe, dst->texture); 1784 ctx->st->flush(ctx->st, 0, &fence, NULL, NULL); 1785 (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE); 1786 screen->fence_reference(screen, &fence, NULL); 1787 } 1788} 1789 1790static void * 1791dri2_map_image(__DRIcontext *context, __DRIimage *image, 1792 int x0, int y0, int width, int height, 1793 unsigned int flags, int *stride, void **data) 1794{ 1795 struct dri_context *ctx = dri_context(context); 1796 struct pipe_context *pipe = ctx->st->pipe; 1797 enum pipe_map_flags pipe_access = 0; 1798 struct pipe_transfer *trans; 1799 void *map; 1800 1801 if (!image || !data || *data) 1802 return NULL; 1803 1804 unsigned plane = image->plane; 1805 if (plane >= dri2_get_mapping_by_format(image->dri_format)->nplanes) 1806 return NULL; 1807 1808 handle_in_fence(context, image); 1809 1810 struct pipe_resource *resource = image->texture; 1811 while (plane--) 1812 resource = resource->next; 1813 1814 if (flags & __DRI_IMAGE_TRANSFER_READ) 1815 pipe_access |= PIPE_MAP_READ; 1816 if (flags & __DRI_IMAGE_TRANSFER_WRITE) 1817 pipe_access |= PIPE_MAP_WRITE; 1818 1819 map = pipe_texture_map(pipe, resource, 0, 0, pipe_access, x0, y0, 1820 width, height, &trans); 1821 if (map) { 1822 *data = trans; 1823 *stride = trans->stride; 1824 } 1825 1826 return map; 1827} 1828 1829static void 1830dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data) 1831{ 1832 struct dri_context *ctx = dri_context(context); 1833 struct pipe_context *pipe = ctx->st->pipe; 1834 1835 pipe_texture_unmap(pipe, (struct pipe_transfer *)data); 1836} 1837 1838static int 1839dri2_get_capabilities(__DRIscreen *_screen) 1840{ 1841 struct dri_screen *screen = dri_screen(_screen); 1842 1843 return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0); 1844} 1845 1846/* The extension is modified during runtime if DRI_PRIME is detected */ 1847static const __DRIimageExtension dri2ImageExtensionTempl = { 1848 .base = { __DRI_IMAGE, 21 }, 1849 1850 .createImageFromName = dri2_create_image_from_name, 1851 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, 1852 .destroyImage = dri2_destroy_image, 1853 .createImage = dri2_create_image, 1854 .queryImage = dri2_query_image, 1855 .dupImage = dri2_dup_image, 1856 .validateUsage = dri2_validate_usage, 1857 .createImageFromNames = dri2_from_names, 1858 .fromPlanar = dri2_from_planar, 1859 .createImageFromTexture = dri2_create_from_texture, 1860 .createImageFromFds = NULL, 1861 .createImageFromFds2 = NULL, 1862 .createImageFromDmaBufs = NULL, 1863 .blitImage = dri2_blit_image, 1864 .getCapabilities = dri2_get_capabilities, 1865 .mapImage = dri2_map_image, 1866 .unmapImage = dri2_unmap_image, 1867 .createImageWithModifiers = NULL, 1868 .createImageFromDmaBufs2 = NULL, 1869 .createImageFromDmaBufs3 = NULL, 1870 .queryDmaBufFormats = NULL, 1871 .queryDmaBufModifiers = NULL, 1872 .queryDmaBufFormatModifierAttribs = NULL, 1873 .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2, 1874 .createImageWithModifiers2 = NULL, 1875}; 1876 1877const __DRIimageExtension driVkImageExtension = { 1878 .base = { __DRI_IMAGE, 20 }, 1879 1880 .createImageFromName = dri2_create_image_from_name, 1881 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, 1882 .destroyImage = dri2_destroy_image, 1883 .createImage = dri2_create_image, 1884 .queryImage = dri2_query_image, 1885 .dupImage = dri2_dup_image, 1886 .validateUsage = dri2_validate_usage, 1887 .createImageFromNames = dri2_from_names, 1888 .fromPlanar = dri2_from_planar, 1889 .createImageFromTexture = dri2_create_from_texture, 1890 .createImageFromFds = dri2_from_fds, 1891 .createImageFromFds2 = dri2_from_fds2, 1892 .createImageFromDmaBufs = dri2_from_dma_bufs, 1893 .blitImage = dri2_blit_image, 1894 .getCapabilities = dri2_get_capabilities, 1895 .mapImage = dri2_map_image, 1896 .unmapImage = dri2_unmap_image, 1897 .createImageWithModifiers = dri2_create_image_with_modifiers, 1898 .createImageFromDmaBufs2 = dri2_from_dma_bufs2, 1899 .createImageFromDmaBufs3 = dri2_from_dma_bufs3, 1900 .queryDmaBufFormats = dri2_query_dma_buf_formats, 1901 .queryDmaBufModifiers = dri2_query_dma_buf_modifiers, 1902 .queryDmaBufFormatModifierAttribs = dri2_query_dma_buf_format_modifier_attribs, 1903 .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2, 1904 .createImageWithModifiers2 = dri2_create_image_with_modifiers2, 1905}; 1906 1907const __DRIimageExtension driVkImageExtensionSw = { 1908 .base = { __DRI_IMAGE, 20 }, 1909 1910 .createImageFromName = dri2_create_image_from_name, 1911 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, 1912 .destroyImage = dri2_destroy_image, 1913 .createImage = dri2_create_image, 1914 .queryImage = dri2_query_image, 1915 .dupImage = dri2_dup_image, 1916 .validateUsage = dri2_validate_usage, 1917 .createImageFromNames = dri2_from_names, 1918 .fromPlanar = dri2_from_planar, 1919 .createImageFromTexture = dri2_create_from_texture, 1920 .createImageFromFds = dri2_from_fds, 1921 .createImageFromFds2 = dri2_from_fds2, 1922 .blitImage = dri2_blit_image, 1923 .getCapabilities = dri2_get_capabilities, 1924 .mapImage = dri2_map_image, 1925 .unmapImage = dri2_unmap_image, 1926 .createImageFromRenderbuffer2 = dri2_create_image_from_renderbuffer2, 1927}; 1928 1929static const __DRIrobustnessExtension dri2Robustness = { 1930 .base = { __DRI2_ROBUSTNESS, 1 } 1931}; 1932 1933static int 1934dri2_interop_query_device_info(__DRIcontext *_ctx, 1935 struct mesa_glinterop_device_info *out) 1936{ 1937 struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen; 1938 1939 /* There is no version 0, thus we do not support it */ 1940 if (out->version == 0) 1941 return MESA_GLINTEROP_INVALID_VERSION; 1942 1943 out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP); 1944 out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS); 1945 out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE); 1946 out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION); 1947 1948 out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID); 1949 out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID); 1950 1951 /* Instruct the caller that we support up-to version one of the interface */ 1952 out->version = 1; 1953 1954 return MESA_GLINTEROP_SUCCESS; 1955} 1956 1957static int 1958dri2_interop_export_object(__DRIcontext *_ctx, 1959 struct mesa_glinterop_export_in *in, 1960 struct mesa_glinterop_export_out *out) 1961{ 1962 struct st_context_iface *st = dri_context(_ctx)->st; 1963 struct pipe_screen *screen = st->pipe->screen; 1964 struct gl_context *ctx = ((struct st_context *)st)->ctx; 1965 struct pipe_resource *res = NULL; 1966 struct winsys_handle whandle; 1967 unsigned target, usage; 1968 boolean success; 1969 1970 /* There is no version 0, thus we do not support it */ 1971 if (in->version == 0 || out->version == 0) 1972 return MESA_GLINTEROP_INVALID_VERSION; 1973 1974 /* Validate the target. */ 1975 switch (in->target) { 1976 case GL_TEXTURE_BUFFER: 1977 case GL_TEXTURE_1D: 1978 case GL_TEXTURE_2D: 1979 case GL_TEXTURE_3D: 1980 case GL_TEXTURE_RECTANGLE: 1981 case GL_TEXTURE_1D_ARRAY: 1982 case GL_TEXTURE_2D_ARRAY: 1983 case GL_TEXTURE_CUBE_MAP_ARRAY: 1984 case GL_TEXTURE_CUBE_MAP: 1985 case GL_TEXTURE_2D_MULTISAMPLE: 1986 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1987 case GL_TEXTURE_EXTERNAL_OES: 1988 case GL_RENDERBUFFER: 1989 case GL_ARRAY_BUFFER: 1990 target = in->target; 1991 break; 1992 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1993 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1994 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1995 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1996 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1997 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 1998 target = GL_TEXTURE_CUBE_MAP; 1999 break; 2000 default: 2001 return MESA_GLINTEROP_INVALID_TARGET; 2002 } 2003 2004 /* Validate the simple case of miplevel. */ 2005 if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) && 2006 in->miplevel != 0) 2007 return MESA_GLINTEROP_INVALID_MIP_LEVEL; 2008 2009 /* Validate the OpenGL object and get pipe_resource. */ 2010 simple_mtx_lock(&ctx->Shared->Mutex); 2011 2012 if (target == GL_ARRAY_BUFFER) { 2013 /* Buffer objects. 2014 * 2015 * The error checking is based on the documentation of 2016 * clCreateFromGLBuffer from OpenCL 2.0 SDK. 2017 */ 2018 struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj); 2019 2020 /* From OpenCL 2.0 SDK, clCreateFromGLBuffer: 2021 * "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is 2022 * a GL buffer object but does not have an existing data store or 2023 * the size of the buffer is 0." 2024 */ 2025 if (!buf || buf->Size == 0) { 2026 simple_mtx_unlock(&ctx->Shared->Mutex); 2027 return MESA_GLINTEROP_INVALID_OBJECT; 2028 } 2029 2030 res = buf->buffer; 2031 if (!res) { 2032 /* this shouldn't happen */ 2033 simple_mtx_unlock(&ctx->Shared->Mutex); 2034 return MESA_GLINTEROP_INVALID_OBJECT; 2035 } 2036 2037 out->buf_offset = 0; 2038 out->buf_size = buf->Size; 2039 2040 buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; 2041 } else if (target == GL_RENDERBUFFER) { 2042 /* Renderbuffers. 2043 * 2044 * The error checking is based on the documentation of 2045 * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK. 2046 */ 2047 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj); 2048 2049 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: 2050 * "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer 2051 * object or if the width or height of renderbuffer is zero." 2052 */ 2053 if (!rb || rb->Width == 0 || rb->Height == 0) { 2054 simple_mtx_unlock(&ctx->Shared->Mutex); 2055 return MESA_GLINTEROP_INVALID_OBJECT; 2056 } 2057 2058 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: 2059 * "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL 2060 * renderbuffer object." 2061 */ 2062 if (rb->NumSamples > 1) { 2063 simple_mtx_unlock(&ctx->Shared->Mutex); 2064 return MESA_GLINTEROP_INVALID_OPERATION; 2065 } 2066 2067 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: 2068 * "CL_OUT_OF_RESOURCES if there is a failure to allocate resources 2069 * required by the OpenCL implementation on the device." 2070 */ 2071 res = rb->texture; 2072 if (!res) { 2073 simple_mtx_unlock(&ctx->Shared->Mutex); 2074 return MESA_GLINTEROP_OUT_OF_RESOURCES; 2075 } 2076 2077 out->internal_format = rb->InternalFormat; 2078 out->view_minlevel = 0; 2079 out->view_numlevels = 1; 2080 out->view_minlayer = 0; 2081 out->view_numlayers = 1; 2082 } else { 2083 /* Texture objects. 2084 * 2085 * The error checking is based on the documentation of 2086 * clCreateFromGLTexture from OpenCL 2.0 SDK. 2087 */ 2088 struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj); 2089 2090 if (obj) 2091 _mesa_test_texobj_completeness(ctx, obj); 2092 2093 /* From OpenCL 2.0 SDK, clCreateFromGLTexture: 2094 * "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose 2095 * type matches texture_target, if the specified miplevel of texture 2096 * is not defined, or if the width or height of the specified 2097 * miplevel is zero or if the GL texture object is incomplete." 2098 */ 2099 if (!obj || 2100 obj->Target != target || 2101 !obj->_BaseComplete || 2102 (in->miplevel > 0 && !obj->_MipmapComplete)) { 2103 simple_mtx_unlock(&ctx->Shared->Mutex); 2104 return MESA_GLINTEROP_INVALID_OBJECT; 2105 } 2106 2107 if (target == GL_TEXTURE_BUFFER) { 2108 struct gl_buffer_object *stBuf = 2109 obj->BufferObject; 2110 2111 if (!stBuf || !stBuf->buffer) { 2112 /* this shouldn't happen */ 2113 simple_mtx_unlock(&ctx->Shared->Mutex); 2114 return MESA_GLINTEROP_INVALID_OBJECT; 2115 } 2116 res = stBuf->buffer; 2117 2118 out->internal_format = obj->BufferObjectFormat; 2119 out->buf_offset = obj->BufferOffset; 2120 out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size : 2121 obj->BufferSize; 2122 2123 obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; 2124 } else { 2125 /* From OpenCL 2.0 SDK, clCreateFromGLTexture: 2126 * "CL_INVALID_MIP_LEVEL if miplevel is less than the value of 2127 * levelbase (for OpenGL implementations) or zero (for OpenGL ES 2128 * implementations); or greater than the value of q (for both OpenGL 2129 * and OpenGL ES). levelbase and q are defined for the texture in 2130 * section 3.8.10 (Texture Completeness) of the OpenGL 2.1 2131 * specification and section 3.7.10 of the OpenGL ES 2.0." 2132 */ 2133 if (in->miplevel < obj->Attrib.BaseLevel || in->miplevel > obj->_MaxLevel) { 2134 simple_mtx_unlock(&ctx->Shared->Mutex); 2135 return MESA_GLINTEROP_INVALID_MIP_LEVEL; 2136 } 2137 2138 if (!st_finalize_texture(ctx, st->pipe, obj, 0)) { 2139 simple_mtx_unlock(&ctx->Shared->Mutex); 2140 return MESA_GLINTEROP_OUT_OF_RESOURCES; 2141 } 2142 2143 res = st_get_texobj_resource(obj); 2144 if (!res) { 2145 /* Incomplete texture buffer object? This shouldn't really occur. */ 2146 simple_mtx_unlock(&ctx->Shared->Mutex); 2147 return MESA_GLINTEROP_INVALID_OBJECT; 2148 } 2149 2150 out->internal_format = obj->Image[0][0]->InternalFormat; 2151 out->view_minlevel = obj->Attrib.MinLevel; 2152 out->view_numlevels = obj->Attrib.NumLevels; 2153 out->view_minlayer = obj->Attrib.MinLayer; 2154 out->view_numlayers = obj->Attrib.NumLayers; 2155 } 2156 } 2157 2158 /* Get the handle. */ 2159 switch (in->access) { 2160 case MESA_GLINTEROP_ACCESS_READ_ONLY: 2161 usage = 0; 2162 break; 2163 case MESA_GLINTEROP_ACCESS_READ_WRITE: 2164 case MESA_GLINTEROP_ACCESS_WRITE_ONLY: 2165 usage = PIPE_HANDLE_USAGE_SHADER_WRITE; 2166 break; 2167 default: 2168 usage = 0; 2169 } 2170 2171 memset(&whandle, 0, sizeof(whandle)); 2172 whandle.type = WINSYS_HANDLE_TYPE_FD; 2173 2174 success = screen->resource_get_handle(screen, st->pipe, res, &whandle, 2175 usage); 2176 simple_mtx_unlock(&ctx->Shared->Mutex); 2177 2178 if (!success) 2179 return MESA_GLINTEROP_OUT_OF_HOST_MEMORY; 2180 2181 out->dmabuf_fd = whandle.handle; 2182 out->out_driver_data_written = 0; 2183 2184 if (res->target == PIPE_BUFFER) 2185 out->buf_offset += whandle.offset; 2186 2187 /* Instruct the caller that we support up-to version one of the interface */ 2188 in->version = 1; 2189 out->version = 1; 2190 2191 return MESA_GLINTEROP_SUCCESS; 2192} 2193 2194static const __DRI2interopExtension dri2InteropExtension = { 2195 .base = { __DRI2_INTEROP, 1 }, 2196 .query_device_info = dri2_interop_query_device_info, 2197 .export_object = dri2_interop_export_object 2198}; 2199 2200/** 2201 * \brief the DRI2bufferDamageExtension set_damage_region method 2202 */ 2203static void 2204dri2_set_damage_region(__DRIdrawable *dPriv, unsigned int nrects, int *rects) 2205{ 2206 struct dri_drawable *drawable = dri_drawable(dPriv); 2207 struct pipe_box *boxes = NULL; 2208 2209 if (nrects) { 2210 boxes = CALLOC(nrects, sizeof(*boxes)); 2211 assert(boxes); 2212 2213 for (unsigned int i = 0; i < nrects; i++) { 2214 int *rect = &rects[i * 4]; 2215 2216 u_box_2d(rect[0], rect[1], rect[2], rect[3], &boxes[i]); 2217 } 2218 } 2219 2220 FREE(drawable->damage_rects); 2221 drawable->damage_rects = boxes; 2222 drawable->num_damage_rects = nrects; 2223 2224 /* Only apply the damage region if the BACK_LEFT texture is up-to-date. */ 2225 if (drawable->texture_stamp == drawable->dPriv->lastStamp && 2226 (drawable->texture_mask & (1 << ST_ATTACHMENT_BACK_LEFT))) { 2227 struct pipe_screen *screen = drawable->screen->base.screen; 2228 struct pipe_resource *resource; 2229 2230 if (drawable->stvis.samples > 1) 2231 resource = drawable->msaa_textures[ST_ATTACHMENT_BACK_LEFT]; 2232 else 2233 resource = drawable->textures[ST_ATTACHMENT_BACK_LEFT]; 2234 2235 screen->set_damage_region(screen, resource, 2236 drawable->num_damage_rects, 2237 drawable->damage_rects); 2238 } 2239} 2240 2241static const __DRI2bufferDamageExtension dri2BufferDamageExtensionTempl = { 2242 .base = { __DRI2_BUFFER_DAMAGE, 1 }, 2243}; 2244 2245/** 2246 * \brief the DRI2ConfigQueryExtension configQueryb method 2247 */ 2248static int 2249dri2GalliumConfigQueryb(__DRIscreen *sPriv, const char *var, 2250 unsigned char *val) 2251{ 2252 struct dri_screen *screen = dri_screen(sPriv); 2253 2254 if (!driCheckOption(&screen->dev->option_cache, var, DRI_BOOL)) 2255 return dri2ConfigQueryExtension.configQueryb(sPriv, var, val); 2256 2257 *val = driQueryOptionb(&screen->dev->option_cache, var); 2258 2259 return 0; 2260} 2261 2262/** 2263 * \brief the DRI2ConfigQueryExtension configQueryi method 2264 */ 2265static int 2266dri2GalliumConfigQueryi(__DRIscreen *sPriv, const char *var, int *val) 2267{ 2268 struct dri_screen *screen = dri_screen(sPriv); 2269 2270 if (!driCheckOption(&screen->dev->option_cache, var, DRI_INT) && 2271 !driCheckOption(&screen->dev->option_cache, var, DRI_ENUM)) 2272 return dri2ConfigQueryExtension.configQueryi(sPriv, var, val); 2273 2274 *val = driQueryOptioni(&screen->dev->option_cache, var); 2275 2276 return 0; 2277} 2278 2279/** 2280 * \brief the DRI2ConfigQueryExtension configQueryf method 2281 */ 2282static int 2283dri2GalliumConfigQueryf(__DRIscreen *sPriv, const char *var, float *val) 2284{ 2285 struct dri_screen *screen = dri_screen(sPriv); 2286 2287 if (!driCheckOption(&screen->dev->option_cache, var, DRI_FLOAT)) 2288 return dri2ConfigQueryExtension.configQueryf(sPriv, var, val); 2289 2290 *val = driQueryOptionf(&screen->dev->option_cache, var); 2291 2292 return 0; 2293} 2294 2295/** 2296 * \brief the DRI2ConfigQueryExtension configQuerys method 2297 */ 2298static int 2299dri2GalliumConfigQuerys(__DRIscreen *sPriv, const char *var, char **val) 2300{ 2301 struct dri_screen *screen = dri_screen(sPriv); 2302 2303 if (!driCheckOption(&screen->dev->option_cache, var, DRI_STRING)) 2304 return dri2ConfigQueryExtension.configQuerys(sPriv, var, val); 2305 2306 *val = driQueryOptionstr(&screen->dev->option_cache, var); 2307 2308 return 0; 2309} 2310 2311/** 2312 * \brief the DRI2ConfigQueryExtension struct. 2313 * 2314 * We first query the driver option cache. Then the dri2 option cache. 2315 */ 2316static const __DRI2configQueryExtension dri2GalliumConfigQueryExtension = { 2317 .base = { __DRI2_CONFIG_QUERY, 2 }, 2318 2319 .configQueryb = dri2GalliumConfigQueryb, 2320 .configQueryi = dri2GalliumConfigQueryi, 2321 .configQueryf = dri2GalliumConfigQueryf, 2322 .configQuerys = dri2GalliumConfigQuerys, 2323}; 2324 2325/** 2326 * \brief the DRI2blobExtension set_cache_funcs method 2327 */ 2328static void 2329set_blob_cache_funcs(__DRIscreen *sPriv, __DRIblobCacheSet set, 2330 __DRIblobCacheGet get) 2331{ 2332 struct dri_screen *screen = dri_screen(sPriv); 2333 struct pipe_screen *pscreen = screen->base.screen; 2334 2335 if (!pscreen->get_disk_shader_cache) 2336 return; 2337 2338 struct disk_cache *cache = pscreen->get_disk_shader_cache(pscreen); 2339 2340 if (!cache) 2341 return; 2342 2343 disk_cache_set_callbacks(cache, set, get); 2344} 2345 2346static const __DRI2blobExtension driBlobExtension = { 2347 .base = { __DRI2_BLOB, 1 }, 2348 .set_cache_funcs = set_blob_cache_funcs 2349}; 2350 2351static const __DRImutableRenderBufferDriverExtension driMutableRenderBufferExtension = { 2352 .base = { __DRI_MUTABLE_RENDER_BUFFER_DRIVER, 1 }, 2353}; 2354 2355/* 2356 * Backend function init_screen. 2357 */ 2358 2359static const __DRIextension *dri_screen_extensions_base[] = { 2360 &driTexBufferExtension.base, 2361 &dri2FlushExtension.base, 2362 &dri2RendererQueryExtension.base, 2363 &dri2GalliumConfigQueryExtension.base, 2364 &dri2ThrottleExtension.base, 2365 &dri2FenceExtension.base, 2366 &dri2InteropExtension.base, 2367 &driBlobExtension.base, 2368 &driMutableRenderBufferExtension.base, 2369 &dri2FlushControlExtension.base, 2370}; 2371 2372/** 2373 * Set up the DRI extension list for this screen based on its underlying 2374 * gallium screen's capabilities. 2375 */ 2376static void 2377dri2_init_screen_extensions(struct dri_screen *screen, 2378 struct pipe_screen *pscreen, 2379 bool is_kms_screen) 2380{ 2381 const __DRIextension **nExt; 2382 2383 STATIC_ASSERT(sizeof(screen->screen_extensions) >= 2384 sizeof(dri_screen_extensions_base)); 2385 memcpy(&screen->screen_extensions, dri_screen_extensions_base, 2386 sizeof(dri_screen_extensions_base)); 2387 screen->sPriv->extensions = screen->screen_extensions; 2388 2389 /* Point nExt at the end of the extension list */ 2390 nExt = &screen->screen_extensions[ARRAY_SIZE(dri_screen_extensions_base)]; 2391 2392 screen->image_extension = dri2ImageExtensionTempl; 2393 if (pscreen->resource_create_with_modifiers) { 2394 screen->image_extension.createImageWithModifiers = 2395 dri2_create_image_with_modifiers; 2396 screen->image_extension.createImageWithModifiers2 = 2397 dri2_create_image_with_modifiers2; 2398 } 2399 2400 if (pscreen->get_param(pscreen, PIPE_CAP_NATIVE_FENCE_FD)) { 2401 screen->image_extension.setInFenceFd = dri2_set_in_fence_fd; 2402 } 2403 2404 if (pscreen->get_param(pscreen, PIPE_CAP_DMABUF)) { 2405 uint64_t cap; 2406 2407 if (drmGetCap(screen->sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && 2408 (cap & DRM_PRIME_CAP_IMPORT)) { 2409 screen->image_extension.createImageFromFds = dri2_from_fds; 2410 screen->image_extension.createImageFromFds2 = dri2_from_fds2; 2411 screen->image_extension.createImageFromDmaBufs = dri2_from_dma_bufs; 2412 screen->image_extension.createImageFromDmaBufs2 = dri2_from_dma_bufs2; 2413 screen->image_extension.createImageFromDmaBufs3 = dri2_from_dma_bufs3; 2414 screen->image_extension.queryDmaBufFormats = 2415 dri2_query_dma_buf_formats; 2416 screen->image_extension.queryDmaBufModifiers = 2417 dri2_query_dma_buf_modifiers; 2418 if (!is_kms_screen) { 2419 screen->image_extension.queryDmaBufFormatModifierAttribs = 2420 dri2_query_dma_buf_format_modifier_attribs; 2421 } 2422 } 2423 } 2424 *nExt++ = &screen->image_extension.base; 2425 2426 if (!is_kms_screen) { 2427 screen->buffer_damage_extension = dri2BufferDamageExtensionTempl; 2428 if (pscreen->set_damage_region) 2429 screen->buffer_damage_extension.set_damage_region = 2430 dri2_set_damage_region; 2431 *nExt++ = &screen->buffer_damage_extension.base; 2432 2433 if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) { 2434 *nExt++ = &dri2Robustness.base; 2435 screen->has_reset_status_query = true; 2436 } 2437 } 2438 2439 /* Ensure the extension list didn't overrun its buffer and is still 2440 * NULL-terminated */ 2441 assert(nExt - screen->screen_extensions <= 2442 ARRAY_SIZE(screen->screen_extensions) - 1); 2443 assert(!*nExt); 2444} 2445 2446/** 2447 * This is the driver specific part of the createNewScreen entry point. 2448 * 2449 * Returns the struct gl_config supported by this driver. 2450 */ 2451static const __DRIconfig ** 2452dri2_init_screen(__DRIscreen * sPriv) 2453{ 2454 const __DRIconfig **configs; 2455 struct dri_screen *screen; 2456 struct pipe_screen *pscreen = NULL; 2457 2458 screen = CALLOC_STRUCT(dri_screen); 2459 if (!screen) 2460 return NULL; 2461 2462 screen->sPriv = sPriv; 2463 screen->fd = sPriv->fd; 2464 (void) mtx_init(&screen->opencl_func_mutex, mtx_plain); 2465 2466 sPriv->driverPrivate = (void *)screen; 2467 2468 if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd)) { 2469 pscreen = pipe_loader_create_screen(screen->dev); 2470 dri_init_options(screen); 2471 } 2472 2473 if (!pscreen) 2474 goto release_pipe; 2475 2476 screen->throttle = pscreen->get_param(pscreen, PIPE_CAP_THROTTLE); 2477 2478 dri2_init_screen_extensions(screen, pscreen, false); 2479 2480 configs = dri_init_screen_helper(screen, pscreen); 2481 if (!configs) 2482 goto destroy_screen; 2483 2484 screen->can_share_buffer = true; 2485 screen->auto_fake_front = dri_with_format(sPriv); 2486 screen->lookup_egl_image = dri2_lookup_egl_image; 2487 2488 const __DRIimageLookupExtension *loader = sPriv->dri2.image; 2489 if (loader && 2490 loader->base.version >= 2 && 2491 loader->validateEGLImage && 2492 loader->lookupEGLImageValidated) { 2493 screen->validate_egl_image = dri2_validate_egl_image; 2494 screen->lookup_egl_image_validated = dri2_lookup_egl_image_validated; 2495 } 2496 2497 return configs; 2498 2499destroy_screen: 2500 dri_destroy_screen_helper(screen); 2501 2502release_pipe: 2503 if (screen->dev) 2504 pipe_loader_release(&screen->dev, 1); 2505 2506 FREE(screen); 2507 return NULL; 2508} 2509 2510/** 2511 * This is the driver specific part of the createNewScreen entry point. 2512 * 2513 * Returns the struct gl_config supported by this driver. 2514 */ 2515static const __DRIconfig ** 2516dri_swrast_kms_init_screen(__DRIscreen * sPriv) 2517{ 2518#if defined(GALLIUM_SOFTPIPE) 2519 const __DRIconfig **configs; 2520 struct dri_screen *screen; 2521 struct pipe_screen *pscreen = NULL; 2522 2523 screen = CALLOC_STRUCT(dri_screen); 2524 if (!screen) 2525 return NULL; 2526 2527 screen->sPriv = sPriv; 2528 screen->fd = sPriv->fd; 2529 2530 sPriv->driverPrivate = (void *)screen; 2531 2532#ifdef HAVE_DRISW_KMS 2533 if (pipe_loader_sw_probe_kms(&screen->dev, screen->fd)) { 2534 pscreen = pipe_loader_create_screen(screen->dev); 2535 dri_init_options(screen); 2536 } 2537#endif 2538 2539 if (!pscreen) 2540 goto release_pipe; 2541 2542 dri2_init_screen_extensions(screen, pscreen, true); 2543 2544 configs = dri_init_screen_helper(screen, pscreen); 2545 if (!configs) 2546 goto destroy_screen; 2547 2548 screen->can_share_buffer = false; 2549 screen->auto_fake_front = dri_with_format(sPriv); 2550 screen->lookup_egl_image = dri2_lookup_egl_image; 2551 2552 const __DRIimageLookupExtension *loader = sPriv->dri2.image; 2553 if (loader && 2554 loader->base.version >= 2 && 2555 loader->validateEGLImage && 2556 loader->lookupEGLImageValidated) { 2557 screen->validate_egl_image = dri2_validate_egl_image; 2558 screen->lookup_egl_image_validated = dri2_lookup_egl_image_validated; 2559 } 2560 2561 return configs; 2562 2563destroy_screen: 2564 dri_destroy_screen_helper(screen); 2565 2566release_pipe: 2567 if (screen->dev) 2568 pipe_loader_release(&screen->dev, 1); 2569 2570 FREE(screen); 2571#endif // GALLIUM_SOFTPIPE 2572 return NULL; 2573} 2574 2575static boolean 2576dri2_create_buffer(__DRIscreen * sPriv, 2577 __DRIdrawable * dPriv, 2578 const struct gl_config * visual, boolean isPixmap) 2579{ 2580 struct dri_drawable *drawable = NULL; 2581 2582 if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) 2583 return FALSE; 2584 2585 drawable = dPriv->driverPrivate; 2586 2587 drawable->allocate_textures = dri2_allocate_textures; 2588 drawable->flush_frontbuffer = dri2_flush_frontbuffer; 2589 drawable->update_tex_buffer = dri2_update_tex_buffer; 2590 drawable->flush_swapbuffers = dri2_flush_swapbuffers; 2591 2592 return TRUE; 2593} 2594 2595/** 2596 * DRI driver virtual function table. 2597 * 2598 * DRI versions differ in their implementation of init_screen and swap_buffers. 2599 */ 2600const struct __DriverAPIRec galliumdrm_driver_api = { 2601 .InitScreen = dri2_init_screen, 2602 .DestroyScreen = dri_destroy_screen, 2603 .CreateBuffer = dri2_create_buffer, 2604 .DestroyBuffer = dri_destroy_buffer, 2605 2606 .AllocateBuffer = dri2_allocate_buffer, 2607 .ReleaseBuffer = dri2_release_buffer, 2608}; 2609 2610static const struct __DRIDriverVtableExtensionRec galliumdrm_vtable = { 2611 .base = { __DRI_DRIVER_VTABLE, 1 }, 2612 .vtable = &galliumdrm_driver_api, 2613}; 2614 2615/** 2616 * DRI driver virtual function table. 2617 * 2618 * KMS/DRM version of the DriverAPI above sporting a different InitScreen 2619 * hook. The latter is used to explicitly initialise the kms_swrast driver 2620 * rather than selecting the approapriate driver as suggested by the loader. 2621 */ 2622const struct __DriverAPIRec dri_swrast_kms_driver_api = { 2623 .InitScreen = dri_swrast_kms_init_screen, 2624 .DestroyScreen = dri_destroy_screen, 2625 .CreateBuffer = dri2_create_buffer, 2626 .DestroyBuffer = dri_destroy_buffer, 2627 2628 .AllocateBuffer = dri2_allocate_buffer, 2629 .ReleaseBuffer = dri2_release_buffer, 2630}; 2631 2632/* This is the table of extensions that the loader will dlsym() for. */ 2633const __DRIextension *galliumdrm_driver_extensions[] = { 2634 &driCoreExtension.base, 2635 &driImageDriverExtension.base, 2636 &driDRI2Extension.base, 2637 &gallium_config_options.base, 2638 &galliumdrm_vtable.base, 2639 NULL 2640}; 2641 2642static const struct __DRIDriverVtableExtensionRec dri_swrast_kms_vtable = { 2643 .base = { __DRI_DRIVER_VTABLE, 1 }, 2644 .vtable = &dri_swrast_kms_driver_api, 2645}; 2646 2647const __DRIextension *dri_swrast_kms_driver_extensions[] = { 2648 &driCoreExtension.base, 2649 &driImageDriverExtension.base, 2650 &swkmsDRI2Extension.base, 2651 &gallium_config_options.base, 2652 &dri_swrast_kms_vtable.base, 2653 NULL 2654}; 2655 2656/* vim: set sw=3 ts=8 sts=3 expandtab: */ 2657