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 <dlfcn.h> 33#include <fcntl.h> 34#include "GL/mesa_glinterop.h" 35#include "util/u_memory.h" 36#include "util/u_inlines.h" 37#include "util/u_format.h" 38#include "util/u_debug.h" 39#include "state_tracker/drm_driver.h" 40#include "state_tracker/st_cb_bufferobjects.h" 41#include "state_tracker/st_cb_fbo.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_screen.h" 50#include "dri_context.h" 51#include "dri_drawable.h" 52#include "dri_query_renderer.h" 53#include "dri2_buffer.h" 54 55static int convert_fourcc(int format, int *dri_components_p) 56{ 57 int dri_components; 58 switch(format) { 59 case __DRI_IMAGE_FOURCC_RGB565: 60 format = __DRI_IMAGE_FORMAT_RGB565; 61 dri_components = __DRI_IMAGE_COMPONENTS_RGB; 62 break; 63 case __DRI_IMAGE_FOURCC_ARGB8888: 64 format = __DRI_IMAGE_FORMAT_ARGB8888; 65 dri_components = __DRI_IMAGE_COMPONENTS_RGBA; 66 break; 67 case __DRI_IMAGE_FOURCC_XRGB8888: 68 format = __DRI_IMAGE_FORMAT_XRGB8888; 69 dri_components = __DRI_IMAGE_COMPONENTS_RGB; 70 break; 71 case __DRI_IMAGE_FOURCC_ABGR8888: 72 format = __DRI_IMAGE_FORMAT_ABGR8888; 73 dri_components = __DRI_IMAGE_COMPONENTS_RGBA; 74 break; 75 case __DRI_IMAGE_FOURCC_XBGR8888: 76 format = __DRI_IMAGE_FORMAT_XBGR8888; 77 dri_components = __DRI_IMAGE_COMPONENTS_RGB; 78 break; 79 case __DRI_IMAGE_FOURCC_R8: 80 format = __DRI_IMAGE_FORMAT_R8; 81 dri_components = __DRI_IMAGE_COMPONENTS_R; 82 break; 83 case __DRI_IMAGE_FOURCC_GR88: 84 format = __DRI_IMAGE_FORMAT_GR88; 85 dri_components = __DRI_IMAGE_COMPONENTS_RG; 86 break; 87 /* 88 * For multi-planar YUV formats, we return the format of the first 89 * plane only. Since there is only one caller which supports multi- 90 * planar YUV it gets to figure out the remaining planes on it's 91 * own. 92 */ 93 case __DRI_IMAGE_FOURCC_YUV420: 94 case __DRI_IMAGE_FOURCC_YVU420: 95 format = __DRI_IMAGE_FORMAT_R8; 96 dri_components = __DRI_IMAGE_COMPONENTS_Y_U_V; 97 break; 98 case __DRI_IMAGE_FOURCC_NV12: 99 format = __DRI_IMAGE_FORMAT_R8; 100 dri_components = __DRI_IMAGE_COMPONENTS_Y_UV; 101 break; 102 default: 103 return -1; 104 } 105 *dri_components_p = dri_components; 106 return format; 107} 108 109/* NOTE this probably isn't going to do the right thing for YUV images 110 * (but I think the same can be said for intel_query_image()). I think 111 * only needed for exporting dmabuf's, so I think I won't loose much 112 * sleep over it. 113 */ 114static int convert_to_fourcc(int format) 115{ 116 switch(format) { 117 case __DRI_IMAGE_FORMAT_RGB565: 118 format = __DRI_IMAGE_FOURCC_RGB565; 119 break; 120 case __DRI_IMAGE_FORMAT_ARGB8888: 121 format = __DRI_IMAGE_FOURCC_ARGB8888; 122 break; 123 case __DRI_IMAGE_FORMAT_XRGB8888: 124 format = __DRI_IMAGE_FOURCC_XRGB8888; 125 break; 126 case __DRI_IMAGE_FORMAT_ABGR8888: 127 format = __DRI_IMAGE_FOURCC_ABGR8888; 128 break; 129 case __DRI_IMAGE_FORMAT_XBGR8888: 130 format = __DRI_IMAGE_FOURCC_XBGR8888; 131 break; 132 case __DRI_IMAGE_FORMAT_R8: 133 format = __DRI_IMAGE_FOURCC_R8; 134 break; 135 case __DRI_IMAGE_FORMAT_GR88: 136 format = __DRI_IMAGE_FOURCC_GR88; 137 break; 138 default: 139 return -1; 140 } 141 return format; 142} 143 144static enum pipe_format dri2_format_to_pipe_format (int format) 145{ 146 enum pipe_format pf; 147 148 switch (format) { 149 case __DRI_IMAGE_FORMAT_RGB565: 150 pf = PIPE_FORMAT_B5G6R5_UNORM; 151 break; 152 case __DRI_IMAGE_FORMAT_XRGB8888: 153 pf = PIPE_FORMAT_BGRX8888_UNORM; 154 break; 155 case __DRI_IMAGE_FORMAT_ARGB8888: 156 pf = PIPE_FORMAT_BGRA8888_UNORM; 157 break; 158 case __DRI_IMAGE_FORMAT_ABGR8888: 159 pf = PIPE_FORMAT_RGBA8888_UNORM; 160 break; 161 case __DRI_IMAGE_FORMAT_R8: 162 pf = PIPE_FORMAT_R8_UNORM; 163 break; 164 case __DRI_IMAGE_FORMAT_GR88: 165 pf = PIPE_FORMAT_RG88_UNORM; 166 break; 167 default: 168 pf = PIPE_FORMAT_NONE; 169 break; 170 } 171 172 return pf; 173} 174 175/** 176 * DRI2 flush extension. 177 */ 178static void 179dri2_flush_drawable(__DRIdrawable *dPriv) 180{ 181 dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1); 182} 183 184static void 185dri2_invalidate_drawable(__DRIdrawable *dPriv) 186{ 187 struct dri_drawable *drawable = dri_drawable(dPriv); 188 189 dri2InvalidateDrawable(dPriv); 190 drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; 191 drawable->texture_mask = 0; 192 193 p_atomic_inc(&drawable->base.stamp); 194} 195 196static const __DRI2flushExtension dri2FlushExtension = { 197 .base = { __DRI2_FLUSH, 4 }, 198 199 .flush = dri2_flush_drawable, 200 .invalidate = dri2_invalidate_drawable, 201 .flush_with_flags = dri_flush, 202}; 203 204/** 205 * Retrieve __DRIbuffer from the DRI loader. 206 */ 207static __DRIbuffer * 208dri2_drawable_get_buffers(struct dri_drawable *drawable, 209 const enum st_attachment_type *atts, 210 unsigned *count) 211{ 212 __DRIdrawable *dri_drawable = drawable->dPriv; 213 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; 214 boolean with_format; 215 __DRIbuffer *buffers; 216 int num_buffers; 217 unsigned attachments[10]; 218 unsigned num_attachments, i; 219 220 assert(loader); 221 with_format = dri_with_format(drawable->sPriv); 222 223 num_attachments = 0; 224 225 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ 226 if (!with_format) 227 attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; 228 229 for (i = 0; i < *count; i++) { 230 enum pipe_format format; 231 unsigned bind; 232 int att, depth; 233 234 dri_drawable_get_format(drawable, atts[i], &format, &bind); 235 if (format == PIPE_FORMAT_NONE) 236 continue; 237 238 switch (atts[i]) { 239 case ST_ATTACHMENT_FRONT_LEFT: 240 /* already added */ 241 if (!with_format) 242 continue; 243 att = __DRI_BUFFER_FRONT_LEFT; 244 break; 245 case ST_ATTACHMENT_BACK_LEFT: 246 att = __DRI_BUFFER_BACK_LEFT; 247 break; 248 case ST_ATTACHMENT_FRONT_RIGHT: 249 att = __DRI_BUFFER_FRONT_RIGHT; 250 break; 251 case ST_ATTACHMENT_BACK_RIGHT: 252 att = __DRI_BUFFER_BACK_RIGHT; 253 break; 254 default: 255 continue; 256 } 257 258 /* 259 * In this switch statement we must support all formats that 260 * may occur as the stvis->color_format. 261 */ 262 switch(format) { 263 case PIPE_FORMAT_BGRA8888_UNORM: 264 depth = 32; 265 break; 266 case PIPE_FORMAT_BGRX8888_UNORM: 267 depth = 24; 268 break; 269 case PIPE_FORMAT_B5G6R5_UNORM: 270 depth = 16; 271 break; 272 default: 273 depth = util_format_get_blocksizebits(format); 274 assert(!"Unexpected format in dri2_drawable_get_buffers()"); 275 } 276 277 attachments[num_attachments++] = att; 278 if (with_format) { 279 attachments[num_attachments++] = depth; 280 } 281 } 282 283 if (with_format) { 284 num_attachments /= 2; 285 buffers = loader->getBuffersWithFormat(dri_drawable, 286 &dri_drawable->w, &dri_drawable->h, 287 attachments, num_attachments, 288 &num_buffers, dri_drawable->loaderPrivate); 289 } 290 else { 291 buffers = loader->getBuffers(dri_drawable, 292 &dri_drawable->w, &dri_drawable->h, 293 attachments, num_attachments, 294 &num_buffers, dri_drawable->loaderPrivate); 295 } 296 297 if (buffers) 298 *count = num_buffers; 299 300 return buffers; 301} 302 303static bool 304dri_image_drawable_get_buffers(struct dri_drawable *drawable, 305 struct __DRIimageList *images, 306 const enum st_attachment_type *statts, 307 unsigned statts_count) 308{ 309 __DRIdrawable *dPriv = drawable->dPriv; 310 __DRIscreen *sPriv = drawable->sPriv; 311 unsigned int image_format = __DRI_IMAGE_FORMAT_NONE; 312 enum pipe_format pf; 313 uint32_t buffer_mask = 0; 314 unsigned i, bind; 315 316 for (i = 0; i < statts_count; i++) { 317 dri_drawable_get_format(drawable, statts[i], &pf, &bind); 318 if (pf == PIPE_FORMAT_NONE) 319 continue; 320 321 switch (statts[i]) { 322 case ST_ATTACHMENT_FRONT_LEFT: 323 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; 324 break; 325 case ST_ATTACHMENT_BACK_LEFT: 326 buffer_mask |= __DRI_IMAGE_BUFFER_BACK; 327 break; 328 default: 329 continue; 330 } 331 332 switch (pf) { 333 case PIPE_FORMAT_B5G6R5_UNORM: 334 image_format = __DRI_IMAGE_FORMAT_RGB565; 335 break; 336 case PIPE_FORMAT_BGRX8888_UNORM: 337 image_format = __DRI_IMAGE_FORMAT_XRGB8888; 338 break; 339 case PIPE_FORMAT_BGRA8888_UNORM: 340 image_format = __DRI_IMAGE_FORMAT_ARGB8888; 341 break; 342 case PIPE_FORMAT_RGBA8888_UNORM: 343 image_format = __DRI_IMAGE_FORMAT_ABGR8888; 344 break; 345 default: 346 image_format = __DRI_IMAGE_FORMAT_NONE; 347 break; 348 } 349 } 350 351 return (*sPriv->image.loader->getBuffers) (dPriv, image_format, 352 (uint32_t *) &drawable->base.stamp, 353 dPriv->loaderPrivate, buffer_mask, 354 images); 355} 356 357static __DRIbuffer * 358dri2_allocate_buffer(__DRIscreen *sPriv, 359 unsigned attachment, unsigned format, 360 int width, int height) 361{ 362 struct dri_screen *screen = dri_screen(sPriv); 363 struct dri2_buffer *buffer; 364 struct pipe_resource templ; 365 enum pipe_format pf; 366 unsigned bind = 0; 367 struct winsys_handle whandle; 368 369 switch (attachment) { 370 case __DRI_BUFFER_FRONT_LEFT: 371 case __DRI_BUFFER_FAKE_FRONT_LEFT: 372 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 373 break; 374 case __DRI_BUFFER_BACK_LEFT: 375 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 376 break; 377 case __DRI_BUFFER_DEPTH: 378 case __DRI_BUFFER_DEPTH_STENCIL: 379 case __DRI_BUFFER_STENCIL: 380 bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ 381 break; 382 } 383 384 /* because we get the handle and stride */ 385 bind |= PIPE_BIND_SHARED; 386 387 switch (format) { 388 case 32: 389 pf = PIPE_FORMAT_BGRA8888_UNORM; 390 break; 391 case 24: 392 pf = PIPE_FORMAT_BGRX8888_UNORM; 393 break; 394 case 16: 395 pf = PIPE_FORMAT_Z16_UNORM; 396 break; 397 default: 398 return NULL; 399 } 400 401 buffer = CALLOC_STRUCT(dri2_buffer); 402 if (!buffer) 403 return NULL; 404 405 memset(&templ, 0, sizeof(templ)); 406 templ.bind = bind; 407 templ.format = pf; 408 templ.target = PIPE_TEXTURE_2D; 409 templ.last_level = 0; 410 templ.width0 = width; 411 templ.height0 = height; 412 templ.depth0 = 1; 413 templ.array_size = 1; 414 415 buffer->resource = 416 screen->base.screen->resource_create(screen->base.screen, &templ); 417 if (!buffer->resource) { 418 FREE(buffer); 419 return NULL; 420 } 421 422 memset(&whandle, 0, sizeof(whandle)); 423 if (screen->can_share_buffer) 424 whandle.type = DRM_API_HANDLE_TYPE_SHARED; 425 else 426 whandle.type = DRM_API_HANDLE_TYPE_KMS; 427 428 screen->base.screen->resource_get_handle(screen->base.screen, NULL, 429 buffer->resource, &whandle, 430 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ); 431 432 buffer->base.attachment = attachment; 433 buffer->base.name = whandle.handle; 434 buffer->base.cpp = util_format_get_blocksize(pf); 435 buffer->base.pitch = whandle.stride; 436 437 return &buffer->base; 438} 439 440static void 441dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) 442{ 443 struct dri2_buffer *buffer = dri2_buffer(bPriv); 444 445 pipe_resource_reference(&buffer->resource, NULL); 446 FREE(buffer); 447} 448 449/* 450 * Backend functions for st_framebuffer interface. 451 */ 452 453static void 454dri2_allocate_textures(struct dri_context *ctx, 455 struct dri_drawable *drawable, 456 const enum st_attachment_type *statts, 457 unsigned statts_count) 458{ 459 __DRIscreen *sPriv = drawable->sPriv; 460 __DRIdrawable *dri_drawable = drawable->dPriv; 461 struct dri_screen *screen = dri_screen(sPriv); 462 struct pipe_resource templ; 463 boolean alloc_depthstencil = FALSE; 464 unsigned i, j, bind; 465 const __DRIimageLoaderExtension *image = sPriv->image.loader; 466 /* Image specific variables */ 467 struct __DRIimageList images; 468 /* Dri2 specific variables */ 469 __DRIbuffer *buffers = NULL; 470 struct winsys_handle whandle; 471 unsigned num_buffers = statts_count; 472 473 /* First get the buffers from the loader */ 474 if (image) { 475 if (!dri_image_drawable_get_buffers(drawable, &images, 476 statts, statts_count)) 477 return; 478 } 479 else { 480 buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); 481 if (!buffers || (drawable->old_num == num_buffers && 482 drawable->old_w == dri_drawable->w && 483 drawable->old_h == dri_drawable->h && 484 memcmp(drawable->old, buffers, 485 sizeof(__DRIbuffer) * num_buffers) == 0)) 486 return; 487 } 488 489 /* Second clean useless resources*/ 490 491 /* See if we need a depth-stencil buffer. */ 492 for (i = 0; i < statts_count; i++) { 493 if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { 494 alloc_depthstencil = TRUE; 495 break; 496 } 497 } 498 499 /* Delete the resources we won't need. */ 500 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 501 /* Don't delete the depth-stencil buffer, we can reuse it. */ 502 if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) 503 continue; 504 505 /* Flush the texture before unreferencing, so that other clients can 506 * see what the driver has rendered. 507 */ 508 if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) { 509 struct pipe_context *pipe = ctx->st->pipe; 510 pipe->flush_resource(pipe, drawable->textures[i]); 511 } 512 513 pipe_resource_reference(&drawable->textures[i], NULL); 514 } 515 516 if (drawable->stvis.samples > 1) { 517 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 518 boolean del = TRUE; 519 520 /* Don't delete MSAA resources for the attachments which are enabled, 521 * we can reuse them. */ 522 for (j = 0; j < statts_count; j++) { 523 if (i == statts[j]) { 524 del = FALSE; 525 break; 526 } 527 } 528 529 if (del) { 530 pipe_resource_reference(&drawable->msaa_textures[i], NULL); 531 } 532 } 533 } 534 535 /* Third use the buffers retrieved to fill the drawable info */ 536 537 memset(&templ, 0, sizeof(templ)); 538 templ.target = screen->target; 539 templ.last_level = 0; 540 templ.depth0 = 1; 541 templ.array_size = 1; 542 543 if (image) { 544 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { 545 struct pipe_resource **buf = 546 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; 547 struct pipe_resource *texture = images.front->texture; 548 549 dri_drawable->w = texture->width0; 550 dri_drawable->h = texture->height0; 551 552 pipe_resource_reference(buf, texture); 553 } 554 555 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { 556 struct pipe_resource **buf = 557 &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; 558 struct pipe_resource *texture = images.back->texture; 559 560 dri_drawable->w = texture->width0; 561 dri_drawable->h = texture->height0; 562 563 pipe_resource_reference(buf, texture); 564 } 565 566 /* Note: if there is both a back and a front buffer, 567 * then they have the same size. 568 */ 569 templ.width0 = dri_drawable->w; 570 templ.height0 = dri_drawable->h; 571 } 572 else { 573 memset(&whandle, 0, sizeof(whandle)); 574 575 /* Process DRI-provided buffers and get pipe_resources. */ 576 for (i = 0; i < num_buffers; i++) { 577 __DRIbuffer *buf = &buffers[i]; 578 enum st_attachment_type statt; 579 enum pipe_format format; 580 581 switch (buf->attachment) { 582 case __DRI_BUFFER_FRONT_LEFT: 583 if (!screen->auto_fake_front) { 584 continue; /* invalid attachment */ 585 } 586 /* fallthrough */ 587 case __DRI_BUFFER_FAKE_FRONT_LEFT: 588 statt = ST_ATTACHMENT_FRONT_LEFT; 589 break; 590 case __DRI_BUFFER_BACK_LEFT: 591 statt = ST_ATTACHMENT_BACK_LEFT; 592 break; 593 default: 594 continue; /* invalid attachment */ 595 } 596 597 dri_drawable_get_format(drawable, statt, &format, &bind); 598 if (format == PIPE_FORMAT_NONE) 599 continue; 600 601 /* dri2_drawable_get_buffers has already filled dri_drawable->w 602 * and dri_drawable->h */ 603 templ.width0 = dri_drawable->w; 604 templ.height0 = dri_drawable->h; 605 templ.format = format; 606 templ.bind = bind; 607 whandle.handle = buf->name; 608 whandle.stride = buf->pitch; 609 whandle.offset = 0; 610 if (screen->can_share_buffer) 611 whandle.type = DRM_API_HANDLE_TYPE_SHARED; 612 else 613 whandle.type = DRM_API_HANDLE_TYPE_KMS; 614 drawable->textures[statt] = 615 screen->base.screen->resource_from_handle(screen->base.screen, 616 &templ, &whandle, 617 PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ); 618 assert(drawable->textures[statt]); 619 } 620 } 621 622 /* Allocate private MSAA colorbuffers. */ 623 if (drawable->stvis.samples > 1) { 624 for (i = 0; i < statts_count; i++) { 625 enum st_attachment_type statt = statts[i]; 626 627 if (statt == ST_ATTACHMENT_DEPTH_STENCIL) 628 continue; 629 630 if (drawable->textures[statt]) { 631 templ.format = drawable->textures[statt]->format; 632 templ.bind = drawable->textures[statt]->bind & ~PIPE_BIND_SCANOUT; 633 templ.nr_samples = drawable->stvis.samples; 634 635 /* Try to reuse the resource. 636 * (the other resource parameters should be constant) 637 */ 638 if (!drawable->msaa_textures[statt] || 639 drawable->msaa_textures[statt]->width0 != templ.width0 || 640 drawable->msaa_textures[statt]->height0 != templ.height0) { 641 /* Allocate a new one. */ 642 pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 643 644 drawable->msaa_textures[statt] = 645 screen->base.screen->resource_create(screen->base.screen, 646 &templ); 647 assert(drawable->msaa_textures[statt]); 648 649 /* If there are any MSAA resources, we should initialize them 650 * such that they contain the same data as the single-sample 651 * resources we just got from the X server. 652 * 653 * The reason for this is that the state tracker (and 654 * therefore the app) can access the MSAA resources only. 655 * The single-sample resources are not exposed 656 * to the state tracker. 657 * 658 */ 659 dri_pipe_blit(ctx->st->pipe, 660 drawable->msaa_textures[statt], 661 drawable->textures[statt]); 662 } 663 } 664 else { 665 pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 666 } 667 } 668 } 669 670 /* Allocate a private depth-stencil buffer. */ 671 if (alloc_depthstencil) { 672 enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL; 673 struct pipe_resource **zsbuf; 674 enum pipe_format format; 675 unsigned bind; 676 677 dri_drawable_get_format(drawable, statt, &format, &bind); 678 679 if (format) { 680 templ.format = format; 681 templ.bind = bind; 682 683 if (drawable->stvis.samples > 1) { 684 templ.nr_samples = drawable->stvis.samples; 685 zsbuf = &drawable->msaa_textures[statt]; 686 } 687 else { 688 templ.nr_samples = 0; 689 zsbuf = &drawable->textures[statt]; 690 } 691 692 /* Try to reuse the resource. 693 * (the other resource parameters should be constant) 694 */ 695 if (!*zsbuf || 696 (*zsbuf)->width0 != templ.width0 || 697 (*zsbuf)->height0 != templ.height0) { 698 /* Allocate a new one. */ 699 pipe_resource_reference(zsbuf, NULL); 700 *zsbuf = screen->base.screen->resource_create(screen->base.screen, 701 &templ); 702 assert(*zsbuf); 703 } 704 } 705 else { 706 pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 707 pipe_resource_reference(&drawable->textures[statt], NULL); 708 } 709 } 710 711 /* For DRI2, we may get the same buffers again from the server. 712 * To prevent useless imports of gem names, drawable->old* is used 713 * to bypass the import if we get the same buffers. This doesn't apply 714 * to DRI3/Wayland, users of image.loader, since the buffer is managed 715 * by the client (no import), and the back buffer is going to change 716 * at every redraw. 717 */ 718 if (!image) { 719 drawable->old_num = num_buffers; 720 drawable->old_w = dri_drawable->w; 721 drawable->old_h = dri_drawable->h; 722 memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers); 723 } 724} 725 726static void 727dri2_flush_frontbuffer(struct dri_context *ctx, 728 struct dri_drawable *drawable, 729 enum st_attachment_type statt) 730{ 731 __DRIdrawable *dri_drawable = drawable->dPriv; 732 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; 733 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; 734 struct pipe_context *pipe = ctx->st->pipe; 735 736 if (statt != ST_ATTACHMENT_FRONT_LEFT) 737 return; 738 739 if (drawable->stvis.samples > 1) { 740 /* Resolve the front buffer. */ 741 dri_pipe_blit(ctx->st->pipe, 742 drawable->textures[ST_ATTACHMENT_FRONT_LEFT], 743 drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); 744 } 745 746 if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) { 747 pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]); 748 } 749 750 pipe->flush(pipe, NULL, 0); 751 752 if (image) { 753 image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); 754 } 755 else if (loader->flushFrontBuffer) { 756 loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); 757 } 758} 759 760static void 761dri2_update_tex_buffer(struct dri_drawable *drawable, 762 struct dri_context *ctx, 763 struct pipe_resource *res) 764{ 765 /* no-op */ 766} 767 768static __DRIimage * 769dri2_lookup_egl_image(struct dri_screen *screen, void *handle) 770{ 771 const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; 772 __DRIimage *img; 773 774 if (!loader->lookupEGLImage) 775 return NULL; 776 777 img = loader->lookupEGLImage(screen->sPriv, 778 handle, screen->sPriv->loaderPrivate); 779 780 return img; 781} 782 783static __DRIimage * 784dri2_create_image_from_winsys(__DRIscreen *_screen, 785 int width, int height, int format, 786 int num_handles, struct winsys_handle *whandle, 787 void *loaderPrivate) 788{ 789 struct dri_screen *screen = dri_screen(_screen); 790 struct pipe_screen *pscreen = screen->base.screen; 791 __DRIimage *img; 792 struct pipe_resource templ; 793 unsigned tex_usage; 794 enum pipe_format pf; 795 int i; 796 797 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 798 799 pf = dri2_format_to_pipe_format (format); 800 if (pf == PIPE_FORMAT_NONE) 801 return NULL; 802 803 img = CALLOC_STRUCT(__DRIimageRec); 804 if (!img) 805 return NULL; 806 807 memset(&templ, 0, sizeof(templ)); 808 templ.bind = tex_usage; 809 templ.target = screen->target; 810 templ.last_level = 0; 811 templ.depth0 = 1; 812 templ.array_size = 1; 813 814 for (i = num_handles - 1; i >= 0; i--) { 815 struct pipe_resource *tex; 816 817 /* TODO: something a lot less ugly */ 818 switch (i) { 819 case 0: 820 templ.width0 = width; 821 templ.height0 = height; 822 templ.format = pf; 823 break; 824 case 1: 825 templ.width0 = width / 2; 826 templ.height0 = height / 2; 827 templ.format = (num_handles == 2) ? 828 PIPE_FORMAT_RG88_UNORM : /* NV12, etc */ 829 PIPE_FORMAT_R8_UNORM; /* I420, etc */ 830 break; 831 case 2: 832 templ.width0 = width / 2; 833 templ.height0 = height / 2; 834 templ.format = PIPE_FORMAT_R8_UNORM; 835 break; 836 default: 837 unreachable("too many planes!"); 838 } 839 840 tex = pscreen->resource_from_handle(pscreen, 841 &templ, &whandle[i], PIPE_HANDLE_USAGE_READ_WRITE); 842 if (!tex) { 843 pipe_resource_reference(&img->texture, NULL); 844 FREE(img); 845 return NULL; 846 } 847 848 tex->next = img->texture; 849 img->texture = tex; 850 } 851 852 img->level = 0; 853 img->layer = 0; 854 img->dri_format = format; 855 img->use = 0; 856 img->loader_private = loaderPrivate; 857 858 return img; 859} 860 861static __DRIimage * 862dri2_create_image_from_name(__DRIscreen *_screen, 863 int width, int height, int format, 864 int name, int pitch, void *loaderPrivate) 865{ 866 struct winsys_handle whandle; 867 enum pipe_format pf; 868 869 memset(&whandle, 0, sizeof(whandle)); 870 whandle.type = DRM_API_HANDLE_TYPE_SHARED; 871 whandle.handle = name; 872 873 pf = dri2_format_to_pipe_format (format); 874 if (pf == PIPE_FORMAT_NONE) 875 return NULL; 876 877 whandle.stride = pitch * util_format_get_blocksize(pf); 878 879 return dri2_create_image_from_winsys(_screen, width, height, format, 880 1, &whandle, loaderPrivate); 881} 882 883static __DRIimage * 884dri2_create_image_from_fd(__DRIscreen *_screen, 885 int width, int height, int fourcc, 886 int *fds, int num_fds, int *strides, 887 int *offsets, unsigned *error, 888 int *dri_components, void *loaderPrivate) 889{ 890 struct winsys_handle whandles[3]; 891 int format; 892 __DRIimage *img = NULL; 893 unsigned err = __DRI_IMAGE_ERROR_SUCCESS; 894 int expected_num_fds, i; 895 896 switch (fourcc) { 897 case __DRI_IMAGE_FOURCC_YUV420: 898 case __DRI_IMAGE_FOURCC_YVU420: 899 expected_num_fds = 3; 900 break; 901 case __DRI_IMAGE_FOURCC_NV12: 902 expected_num_fds = 2; 903 break; 904 default: 905 expected_num_fds = 1; 906 break; 907 } 908 909 if (num_fds != expected_num_fds) { 910 err = __DRI_IMAGE_ERROR_BAD_MATCH; 911 goto exit; 912 } 913 914 format = convert_fourcc(fourcc, dri_components); 915 if (format == -1) { 916 err = __DRI_IMAGE_ERROR_BAD_MATCH; 917 goto exit; 918 } 919 920 memset(whandles, 0, sizeof(whandles)); 921 922 for (i = 0; i < num_fds; i++) { 923 if (fds[i] < 0) { 924 err = __DRI_IMAGE_ERROR_BAD_ALLOC; 925 goto exit; 926 } 927 928 whandles[i].type = DRM_API_HANDLE_TYPE_FD; 929 whandles[i].handle = (unsigned)fds[i]; 930 whandles[i].stride = (unsigned)strides[i]; 931 whandles[i].offset = (unsigned)offsets[i]; 932 } 933 934 if (fourcc == __DRI_IMAGE_FOURCC_YVU420) { 935 /* convert to YUV420 by swapping 2nd and 3rd planes: */ 936 struct winsys_handle tmp = whandles[1]; 937 whandles[1] = whandles[2]; 938 whandles[2] = tmp; 939 fourcc = __DRI_IMAGE_FOURCC_YUV420; 940 } 941 942 img = dri2_create_image_from_winsys(_screen, width, height, format, 943 num_fds, whandles, loaderPrivate); 944 if(img == NULL) 945 err = __DRI_IMAGE_ERROR_BAD_ALLOC; 946 947exit: 948 if (error) 949 *error = err; 950 951 return img; 952} 953 954static __DRIimage * 955dri2_create_image_from_renderbuffer(__DRIcontext *context, 956 int renderbuffer, void *loaderPrivate) 957{ 958 struct dri_context *ctx = dri_context(context); 959 960 if (!ctx->st->get_resource_for_egl_image) 961 return NULL; 962 963 /* TODO */ 964 return NULL; 965} 966 967static __DRIimage * 968dri2_create_image(__DRIscreen *_screen, 969 int width, int height, int format, 970 unsigned int use, void *loaderPrivate) 971{ 972 struct dri_screen *screen = dri_screen(_screen); 973 __DRIimage *img; 974 struct pipe_resource templ; 975 unsigned tex_usage; 976 enum pipe_format pf; 977 978 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 979 if (use & __DRI_IMAGE_USE_SCANOUT) 980 tex_usage |= PIPE_BIND_SCANOUT; 981 if (use & __DRI_IMAGE_USE_SHARE) 982 tex_usage |= PIPE_BIND_SHARED; 983 if (use & __DRI_IMAGE_USE_LINEAR) 984 tex_usage |= PIPE_BIND_LINEAR; 985 if (use & __DRI_IMAGE_USE_CURSOR) { 986 if (width != 64 || height != 64) 987 return NULL; 988 tex_usage |= PIPE_BIND_CURSOR; 989 } 990 991 pf = dri2_format_to_pipe_format (format); 992 if (pf == PIPE_FORMAT_NONE) 993 return NULL; 994 995 img = CALLOC_STRUCT(__DRIimageRec); 996 if (!img) 997 return NULL; 998 999 memset(&templ, 0, sizeof(templ)); 1000 templ.bind = tex_usage; 1001 templ.format = pf; 1002 templ.target = PIPE_TEXTURE_2D; 1003 templ.last_level = 0; 1004 templ.width0 = width; 1005 templ.height0 = height; 1006 templ.depth0 = 1; 1007 templ.array_size = 1; 1008 1009 img->texture = screen->base.screen->resource_create(screen->base.screen, &templ); 1010 if (!img->texture) { 1011 FREE(img); 1012 return NULL; 1013 } 1014 1015 img->level = 0; 1016 img->layer = 0; 1017 img->dri_format = format; 1018 img->dri_components = 0; 1019 img->use = use; 1020 1021 img->loader_private = loaderPrivate; 1022 return img; 1023} 1024 1025static GLboolean 1026dri2_query_image(__DRIimage *image, int attrib, int *value) 1027{ 1028 struct winsys_handle whandle; 1029 unsigned usage; 1030 1031 if (image->use & __DRI_IMAGE_USE_BACKBUFFER) 1032 usage = PIPE_HANDLE_USAGE_EXPLICIT_FLUSH | PIPE_HANDLE_USAGE_READ; 1033 else 1034 usage = PIPE_HANDLE_USAGE_READ_WRITE; 1035 1036 memset(&whandle, 0, sizeof(whandle)); 1037 1038 switch (attrib) { 1039 case __DRI_IMAGE_ATTRIB_STRIDE: 1040 whandle.type = DRM_API_HANDLE_TYPE_KMS; 1041 image->texture->screen->resource_get_handle(image->texture->screen, 1042 NULL, image->texture, &whandle, usage); 1043 *value = whandle.stride; 1044 return GL_TRUE; 1045 case __DRI_IMAGE_ATTRIB_HANDLE: 1046 whandle.type = DRM_API_HANDLE_TYPE_KMS; 1047 image->texture->screen->resource_get_handle(image->texture->screen, 1048 NULL, image->texture, &whandle, usage); 1049 *value = whandle.handle; 1050 return GL_TRUE; 1051 case __DRI_IMAGE_ATTRIB_NAME: 1052 whandle.type = DRM_API_HANDLE_TYPE_SHARED; 1053 image->texture->screen->resource_get_handle(image->texture->screen, 1054 NULL, image->texture, &whandle, usage); 1055 *value = whandle.handle; 1056 return GL_TRUE; 1057 case __DRI_IMAGE_ATTRIB_FD: 1058 whandle.type= DRM_API_HANDLE_TYPE_FD; 1059 if (!image->texture->screen->resource_get_handle(image->texture->screen, 1060 NULL, image->texture, &whandle, usage)) 1061 return GL_FALSE; 1062 1063 *value = whandle.handle; 1064 return GL_TRUE; 1065 case __DRI_IMAGE_ATTRIB_FORMAT: 1066 *value = image->dri_format; 1067 return GL_TRUE; 1068 case __DRI_IMAGE_ATTRIB_WIDTH: 1069 *value = image->texture->width0; 1070 return GL_TRUE; 1071 case __DRI_IMAGE_ATTRIB_HEIGHT: 1072 *value = image->texture->height0; 1073 return GL_TRUE; 1074 case __DRI_IMAGE_ATTRIB_COMPONENTS: 1075 if (image->dri_components == 0) 1076 return GL_FALSE; 1077 *value = image->dri_components; 1078 return GL_TRUE; 1079 case __DRI_IMAGE_ATTRIB_FOURCC: 1080 *value = convert_to_fourcc(image->dri_format); 1081 return GL_TRUE; 1082 case __DRI_IMAGE_ATTRIB_NUM_PLANES: 1083 *value = 1; 1084 return GL_TRUE; 1085 default: 1086 return GL_FALSE; 1087 } 1088} 1089 1090static __DRIimage * 1091dri2_dup_image(__DRIimage *image, void *loaderPrivate) 1092{ 1093 __DRIimage *img; 1094 1095 img = CALLOC_STRUCT(__DRIimageRec); 1096 if (!img) 1097 return NULL; 1098 1099 img->texture = NULL; 1100 pipe_resource_reference(&img->texture, image->texture); 1101 img->level = image->level; 1102 img->layer = image->layer; 1103 img->dri_format = image->dri_format; 1104 /* This should be 0 for sub images, but dup is also used for base images. */ 1105 img->dri_components = image->dri_components; 1106 img->loader_private = loaderPrivate; 1107 1108 return img; 1109} 1110 1111static GLboolean 1112dri2_validate_usage(__DRIimage *image, unsigned int use) 1113{ 1114 /* 1115 * Gallium drivers are bad at adding usages to the resources 1116 * once opened again in another process, which is the main use 1117 * case for this, so we have to lie. 1118 */ 1119 if (image != NULL) 1120 return GL_TRUE; 1121 else 1122 return GL_FALSE; 1123} 1124 1125static __DRIimage * 1126dri2_from_names(__DRIscreen *screen, int width, int height, int format, 1127 int *names, int num_names, int *strides, int *offsets, 1128 void *loaderPrivate) 1129{ 1130 __DRIimage *img; 1131 int dri_components; 1132 struct winsys_handle whandle; 1133 1134 if (num_names != 1) 1135 return NULL; 1136 1137 format = convert_fourcc(format, &dri_components); 1138 if (format == -1) 1139 return NULL; 1140 1141 memset(&whandle, 0, sizeof(whandle)); 1142 whandle.type = DRM_API_HANDLE_TYPE_SHARED; 1143 whandle.handle = names[0]; 1144 whandle.stride = strides[0]; 1145 whandle.offset = offsets[0]; 1146 1147 img = dri2_create_image_from_winsys(screen, width, height, format, 1148 1, &whandle, loaderPrivate); 1149 if (img == NULL) 1150 return NULL; 1151 1152 img->dri_components = dri_components; 1153 return img; 1154} 1155 1156static __DRIimage * 1157dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) 1158{ 1159 __DRIimage *img; 1160 1161 if (plane != 0) 1162 return NULL; 1163 1164 if (image->dri_components == 0) 1165 return NULL; 1166 1167 img = dri2_dup_image(image, loaderPrivate); 1168 if (img == NULL) 1169 return NULL; 1170 1171 /* set this to 0 for sub images. */ 1172 img->dri_components = 0; 1173 return img; 1174} 1175 1176static __DRIimage * 1177dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, 1178 int depth, int level, unsigned *error, 1179 void *loaderPrivate) 1180{ 1181 __DRIimage *img; 1182 struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx; 1183 struct gl_texture_object *obj; 1184 struct pipe_resource *tex; 1185 GLuint face = 0; 1186 1187 obj = _mesa_lookup_texture(ctx, texture); 1188 if (!obj || obj->Target != target) { 1189 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 1190 return NULL; 1191 } 1192 1193 tex = st_get_texobj_resource(obj); 1194 if (!tex) { 1195 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 1196 return NULL; 1197 } 1198 1199 if (target == GL_TEXTURE_CUBE_MAP) 1200 face = depth; 1201 1202 _mesa_test_texobj_completeness(ctx, obj); 1203 if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { 1204 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 1205 return NULL; 1206 } 1207 1208 if (level < obj->BaseLevel || level > obj->_MaxLevel) { 1209 *error = __DRI_IMAGE_ERROR_BAD_MATCH; 1210 return NULL; 1211 } 1212 1213 if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) { 1214 *error = __DRI_IMAGE_ERROR_BAD_MATCH; 1215 return NULL; 1216 } 1217 1218 img = CALLOC_STRUCT(__DRIimageRec); 1219 if (!img) { 1220 *error = __DRI_IMAGE_ERROR_BAD_ALLOC; 1221 return NULL; 1222 } 1223 1224 img->level = level; 1225 img->layer = depth; 1226 img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat); 1227 1228 img->loader_private = loaderPrivate; 1229 1230 if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) { 1231 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 1232 free(img); 1233 return NULL; 1234 } 1235 1236 pipe_resource_reference(&img->texture, tex); 1237 1238 *error = __DRI_IMAGE_ERROR_SUCCESS; 1239 return img; 1240} 1241 1242static __DRIimage * 1243dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc, 1244 int *fds, int num_fds, int *strides, int *offsets, 1245 void *loaderPrivate) 1246{ 1247 __DRIimage *img; 1248 int dri_components; 1249 1250 img = dri2_create_image_from_fd(screen, width, height, fourcc, 1251 fds, num_fds, strides, offsets, NULL, 1252 &dri_components, loaderPrivate); 1253 if (img == NULL) 1254 return NULL; 1255 1256 img->dri_components = dri_components; 1257 return img; 1258} 1259 1260static __DRIimage * 1261dri2_from_dma_bufs(__DRIscreen *screen, 1262 int width, int height, int fourcc, 1263 int *fds, int num_fds, 1264 int *strides, int *offsets, 1265 enum __DRIYUVColorSpace yuv_color_space, 1266 enum __DRISampleRange sample_range, 1267 enum __DRIChromaSiting horizontal_siting, 1268 enum __DRIChromaSiting vertical_siting, 1269 unsigned *error, 1270 void *loaderPrivate) 1271{ 1272 __DRIimage *img; 1273 int dri_components; 1274 1275 img = dri2_create_image_from_fd(screen, width, height, fourcc, 1276 fds, num_fds, strides, offsets, error, 1277 &dri_components, loaderPrivate); 1278 if (img == NULL) 1279 return NULL; 1280 1281 img->yuv_color_space = yuv_color_space; 1282 img->sample_range = sample_range; 1283 img->horizontal_siting = horizontal_siting; 1284 img->vertical_siting = vertical_siting; 1285 img->dri_components = dri_components; 1286 1287 *error = __DRI_IMAGE_ERROR_SUCCESS; 1288 return img; 1289} 1290 1291static void 1292dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src, 1293 int dstx0, int dsty0, int dstwidth, int dstheight, 1294 int srcx0, int srcy0, int srcwidth, int srcheight, 1295 int flush_flag) 1296{ 1297 struct dri_context *ctx = dri_context(context); 1298 struct pipe_context *pipe = ctx->st->pipe; 1299 struct pipe_screen *screen; 1300 struct pipe_fence_handle *fence; 1301 struct pipe_blit_info blit; 1302 1303 if (!dst || !src) 1304 return; 1305 1306 memset(&blit, 0, sizeof(blit)); 1307 blit.dst.resource = dst->texture; 1308 blit.dst.box.x = dstx0; 1309 blit.dst.box.y = dsty0; 1310 blit.dst.box.width = dstwidth; 1311 blit.dst.box.height = dstheight; 1312 blit.dst.box.depth = 1; 1313 blit.dst.format = dst->texture->format; 1314 blit.src.resource = src->texture; 1315 blit.src.box.x = srcx0; 1316 blit.src.box.y = srcy0; 1317 blit.src.box.width = srcwidth; 1318 blit.src.box.height = srcheight; 1319 blit.src.box.depth = 1; 1320 blit.src.format = src->texture->format; 1321 blit.mask = PIPE_MASK_RGBA; 1322 blit.filter = PIPE_TEX_FILTER_NEAREST; 1323 1324 pipe->blit(pipe, &blit); 1325 1326 if (flush_flag == __BLIT_FLAG_FLUSH) { 1327 pipe->flush_resource(pipe, dst->texture); 1328 ctx->st->flush(ctx->st, 0, NULL); 1329 } else if (flush_flag == __BLIT_FLAG_FINISH) { 1330 screen = dri_screen(ctx->sPriv)->base.screen; 1331 pipe->flush_resource(pipe, dst->texture); 1332 ctx->st->flush(ctx->st, 0, &fence); 1333 (void) screen->fence_finish(screen, NULL, fence, PIPE_TIMEOUT_INFINITE); 1334 screen->fence_reference(screen, &fence, NULL); 1335 } 1336} 1337 1338static void * 1339dri2_map_image(__DRIcontext *context, __DRIimage *image, 1340 int x0, int y0, int width, int height, 1341 unsigned int flags, int *stride, void **data) 1342{ 1343 struct dri_context *ctx = dri_context(context); 1344 struct pipe_context *pipe = ctx->st->pipe; 1345 enum pipe_transfer_usage pipe_access = 0; 1346 struct pipe_transfer *trans; 1347 void *map; 1348 1349 if (!image || !data || *data) 1350 return NULL; 1351 1352 if (flags & __DRI_IMAGE_TRANSFER_READ) 1353 pipe_access |= PIPE_TRANSFER_READ; 1354 if (flags & __DRI_IMAGE_TRANSFER_WRITE) 1355 pipe_access |= PIPE_TRANSFER_WRITE; 1356 1357 map = pipe_transfer_map(pipe, image->texture, 1358 0, 0, pipe_access, x0, y0, width, height, 1359 &trans); 1360 if (map) { 1361 *data = trans; 1362 *stride = trans->stride; 1363 } 1364 1365 return map; 1366} 1367 1368static void 1369dri2_unmap_image(__DRIcontext *context, __DRIimage *image, void *data) 1370{ 1371 struct dri_context *ctx = dri_context(context); 1372 struct pipe_context *pipe = ctx->st->pipe; 1373 1374 pipe_transfer_unmap(pipe, (struct pipe_transfer *)data); 1375} 1376 1377static void 1378dri2_destroy_image(__DRIimage *img) 1379{ 1380 pipe_resource_reference(&img->texture, NULL); 1381 FREE(img); 1382} 1383 1384static int 1385dri2_get_capabilities(__DRIscreen *_screen) 1386{ 1387 struct dri_screen *screen = dri_screen(_screen); 1388 1389 return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0); 1390} 1391 1392/* The extension is modified during runtime if DRI_PRIME is detected */ 1393static __DRIimageExtension dri2ImageExtension = { 1394 .base = { __DRI_IMAGE, 12 }, 1395 1396 .createImageFromName = dri2_create_image_from_name, 1397 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, 1398 .destroyImage = dri2_destroy_image, 1399 .createImage = dri2_create_image, 1400 .queryImage = dri2_query_image, 1401 .dupImage = dri2_dup_image, 1402 .validateUsage = dri2_validate_usage, 1403 .createImageFromNames = dri2_from_names, 1404 .fromPlanar = dri2_from_planar, 1405 .createImageFromTexture = dri2_create_from_texture, 1406 .createImageFromFds = NULL, 1407 .createImageFromDmaBufs = NULL, 1408 .blitImage = dri2_blit_image, 1409 .getCapabilities = dri2_get_capabilities, 1410 .mapImage = dri2_map_image, 1411 .unmapImage = dri2_unmap_image, 1412}; 1413 1414 1415static bool 1416dri2_is_opencl_interop_loaded_locked(struct dri_screen *screen) 1417{ 1418 return screen->opencl_dri_event_add_ref && 1419 screen->opencl_dri_event_release && 1420 screen->opencl_dri_event_wait && 1421 screen->opencl_dri_event_get_fence; 1422} 1423 1424static bool 1425dri2_load_opencl_interop(struct dri_screen *screen) 1426{ 1427#if defined(RTLD_DEFAULT) 1428 bool success; 1429 1430 pipe_mutex_lock(screen->opencl_func_mutex); 1431 1432 if (dri2_is_opencl_interop_loaded_locked(screen)) { 1433 pipe_mutex_unlock(screen->opencl_func_mutex); 1434 return true; 1435 } 1436 1437 screen->opencl_dri_event_add_ref = 1438 dlsym(RTLD_DEFAULT, "opencl_dri_event_add_ref"); 1439 screen->opencl_dri_event_release = 1440 dlsym(RTLD_DEFAULT, "opencl_dri_event_release"); 1441 screen->opencl_dri_event_wait = 1442 dlsym(RTLD_DEFAULT, "opencl_dri_event_wait"); 1443 screen->opencl_dri_event_get_fence = 1444 dlsym(RTLD_DEFAULT, "opencl_dri_event_get_fence"); 1445 1446 success = dri2_is_opencl_interop_loaded_locked(screen); 1447 pipe_mutex_unlock(screen->opencl_func_mutex); 1448 return success; 1449#else 1450 return false; 1451#endif 1452} 1453 1454struct dri2_fence { 1455 struct dri_screen *driscreen; 1456 struct pipe_fence_handle *pipe_fence; 1457 void *cl_event; 1458}; 1459 1460static unsigned dri2_fence_get_caps(__DRIscreen *_screen) 1461{ 1462 struct dri_screen *driscreen = dri_screen(_screen); 1463 struct pipe_screen *screen = driscreen->base.screen; 1464 unsigned caps = 0; 1465 1466 if (screen->get_param(screen, PIPE_CAP_NATIVE_FENCE_FD)) 1467 caps |= __DRI_FENCE_CAP_NATIVE_FD; 1468 1469 return caps; 1470} 1471 1472static void * 1473dri2_create_fence(__DRIcontext *_ctx) 1474{ 1475 struct pipe_context *ctx = dri_context(_ctx)->st->pipe; 1476 struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence); 1477 1478 if (!fence) 1479 return NULL; 1480 1481 ctx->flush(ctx, &fence->pipe_fence, 0); 1482 1483 if (!fence->pipe_fence) { 1484 FREE(fence); 1485 return NULL; 1486 } 1487 1488 fence->driscreen = dri_screen(_ctx->driScreenPriv); 1489 return fence; 1490} 1491 1492static void * 1493dri2_create_fence_fd(__DRIcontext *_ctx, int fd) 1494{ 1495 struct pipe_context *ctx = dri_context(_ctx)->st->pipe; 1496 struct dri2_fence *fence = CALLOC_STRUCT(dri2_fence); 1497 1498 if (fd == -1) { 1499 /* exporting driver created fence, flush: */ 1500 ctx->flush(ctx, &fence->pipe_fence, 1501 PIPE_FLUSH_DEFERRED | PIPE_FLUSH_FENCE_FD); 1502 } else { 1503 /* importing a foreign fence fd: */ 1504 ctx->create_fence_fd(ctx, &fence->pipe_fence, fd); 1505 } 1506 if (!fence->pipe_fence) { 1507 FREE(fence); 1508 return NULL; 1509 } 1510 1511 fence->driscreen = dri_screen(_ctx->driScreenPriv); 1512 return fence; 1513} 1514 1515static int 1516dri2_get_fence_fd(__DRIscreen *_screen, void *_fence) 1517{ 1518 struct dri_screen *driscreen = dri_screen(_screen); 1519 struct pipe_screen *screen = driscreen->base.screen; 1520 struct dri2_fence *fence = (struct dri2_fence*)_fence; 1521 1522 return screen->fence_get_fd(screen, fence->pipe_fence); 1523} 1524 1525static void * 1526dri2_get_fence_from_cl_event(__DRIscreen *_screen, intptr_t cl_event) 1527{ 1528 struct dri_screen *driscreen = dri_screen(_screen); 1529 struct dri2_fence *fence; 1530 1531 if (!dri2_load_opencl_interop(driscreen)) 1532 return NULL; 1533 1534 fence = CALLOC_STRUCT(dri2_fence); 1535 if (!fence) 1536 return NULL; 1537 1538 fence->cl_event = (void*)cl_event; 1539 1540 if (!driscreen->opencl_dri_event_add_ref(fence->cl_event)) { 1541 free(fence); 1542 return NULL; 1543 } 1544 1545 fence->driscreen = driscreen; 1546 return fence; 1547} 1548 1549static void 1550dri2_destroy_fence(__DRIscreen *_screen, void *_fence) 1551{ 1552 struct dri_screen *driscreen = dri_screen(_screen); 1553 struct pipe_screen *screen = driscreen->base.screen; 1554 struct dri2_fence *fence = (struct dri2_fence*)_fence; 1555 1556 if (fence->pipe_fence) 1557 screen->fence_reference(screen, &fence->pipe_fence, NULL); 1558 else if (fence->cl_event) 1559 driscreen->opencl_dri_event_release(fence->cl_event); 1560 else 1561 assert(0); 1562 1563 FREE(fence); 1564} 1565 1566static GLboolean 1567dri2_client_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags, 1568 uint64_t timeout) 1569{ 1570 struct dri2_fence *fence = (struct dri2_fence*)_fence; 1571 struct dri_screen *driscreen = fence->driscreen; 1572 struct pipe_screen *screen = driscreen->base.screen; 1573 1574 /* No need to flush. The context was flushed when the fence was created. */ 1575 1576 if (fence->pipe_fence) 1577 return screen->fence_finish(screen, NULL, fence->pipe_fence, timeout); 1578 else if (fence->cl_event) { 1579 struct pipe_fence_handle *pipe_fence = 1580 driscreen->opencl_dri_event_get_fence(fence->cl_event); 1581 1582 if (pipe_fence) 1583 return screen->fence_finish(screen, NULL, pipe_fence, timeout); 1584 else 1585 return driscreen->opencl_dri_event_wait(fence->cl_event, timeout); 1586 } 1587 else { 1588 assert(0); 1589 return false; 1590 } 1591} 1592 1593static void 1594dri2_server_wait_sync(__DRIcontext *_ctx, void *_fence, unsigned flags) 1595{ 1596 struct pipe_context *ctx = dri_context(_ctx)->st->pipe; 1597 struct dri2_fence *fence = (struct dri2_fence*)_fence; 1598 1599 if (ctx->fence_server_sync) 1600 ctx->fence_server_sync(ctx, fence->pipe_fence); 1601} 1602 1603static __DRI2fenceExtension dri2FenceExtension = { 1604 .base = { __DRI2_FENCE, 2 }, 1605 1606 .create_fence = dri2_create_fence, 1607 .get_fence_from_cl_event = dri2_get_fence_from_cl_event, 1608 .destroy_fence = dri2_destroy_fence, 1609 .client_wait_sync = dri2_client_wait_sync, 1610 .server_wait_sync = dri2_server_wait_sync, 1611 .get_capabilities = dri2_fence_get_caps, 1612 .create_fence_fd = dri2_create_fence_fd, 1613 .get_fence_fd = dri2_get_fence_fd, 1614}; 1615 1616static const __DRIrobustnessExtension dri2Robustness = { 1617 .base = { __DRI2_ROBUSTNESS, 1 } 1618}; 1619 1620static int 1621dri2_interop_query_device_info(__DRIcontext *_ctx, 1622 struct mesa_glinterop_device_info *out) 1623{ 1624 struct pipe_screen *screen = dri_context(_ctx)->st->pipe->screen; 1625 1626 /* There is no version 0, thus we do not support it */ 1627 if (out->version == 0) 1628 return MESA_GLINTEROP_INVALID_VERSION; 1629 1630 out->pci_segment_group = screen->get_param(screen, PIPE_CAP_PCI_GROUP); 1631 out->pci_bus = screen->get_param(screen, PIPE_CAP_PCI_BUS); 1632 out->pci_device = screen->get_param(screen, PIPE_CAP_PCI_DEVICE); 1633 out->pci_function = screen->get_param(screen, PIPE_CAP_PCI_FUNCTION); 1634 1635 out->vendor_id = screen->get_param(screen, PIPE_CAP_VENDOR_ID); 1636 out->device_id = screen->get_param(screen, PIPE_CAP_DEVICE_ID); 1637 1638 /* Instruct the caller that we support up-to version one of the interface */ 1639 out->version = 1; 1640 1641 return MESA_GLINTEROP_SUCCESS; 1642} 1643 1644static int 1645dri2_interop_export_object(__DRIcontext *_ctx, 1646 struct mesa_glinterop_export_in *in, 1647 struct mesa_glinterop_export_out *out) 1648{ 1649 struct st_context_iface *st = dri_context(_ctx)->st; 1650 struct pipe_screen *screen = st->pipe->screen; 1651 struct gl_context *ctx = ((struct st_context *)st)->ctx; 1652 struct pipe_resource *res = NULL; 1653 struct winsys_handle whandle; 1654 unsigned target, usage; 1655 boolean success; 1656 1657 /* There is no version 0, thus we do not support it */ 1658 if (in->version == 0 || out->version == 0) 1659 return MESA_GLINTEROP_INVALID_VERSION; 1660 1661 /* Validate the target. */ 1662 switch (in->target) { 1663 case GL_TEXTURE_BUFFER: 1664 case GL_TEXTURE_1D: 1665 case GL_TEXTURE_2D: 1666 case GL_TEXTURE_3D: 1667 case GL_TEXTURE_RECTANGLE: 1668 case GL_TEXTURE_1D_ARRAY: 1669 case GL_TEXTURE_2D_ARRAY: 1670 case GL_TEXTURE_CUBE_MAP_ARRAY: 1671 case GL_TEXTURE_CUBE_MAP: 1672 case GL_TEXTURE_2D_MULTISAMPLE: 1673 case GL_TEXTURE_2D_MULTISAMPLE_ARRAY: 1674 case GL_TEXTURE_EXTERNAL_OES: 1675 case GL_RENDERBUFFER: 1676 case GL_ARRAY_BUFFER: 1677 target = in->target; 1678 break; 1679 case GL_TEXTURE_CUBE_MAP_POSITIVE_X: 1680 case GL_TEXTURE_CUBE_MAP_NEGATIVE_X: 1681 case GL_TEXTURE_CUBE_MAP_POSITIVE_Y: 1682 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Y: 1683 case GL_TEXTURE_CUBE_MAP_POSITIVE_Z: 1684 case GL_TEXTURE_CUBE_MAP_NEGATIVE_Z: 1685 target = GL_TEXTURE_CUBE_MAP; 1686 break; 1687 default: 1688 return MESA_GLINTEROP_INVALID_TARGET; 1689 } 1690 1691 /* Validate the simple case of miplevel. */ 1692 if ((target == GL_RENDERBUFFER || target == GL_ARRAY_BUFFER) && 1693 in->miplevel != 0) 1694 return MESA_GLINTEROP_INVALID_MIP_LEVEL; 1695 1696 /* Validate the OpenGL object and get pipe_resource. */ 1697 mtx_lock(&ctx->Shared->Mutex); 1698 1699 if (target == GL_ARRAY_BUFFER) { 1700 /* Buffer objects. 1701 * 1702 * The error checking is based on the documentation of 1703 * clCreateFromGLBuffer from OpenCL 2.0 SDK. 1704 */ 1705 struct gl_buffer_object *buf = _mesa_lookup_bufferobj(ctx, in->obj); 1706 1707 /* From OpenCL 2.0 SDK, clCreateFromGLBuffer: 1708 * "CL_INVALID_GL_OBJECT if bufobj is not a GL buffer object or is 1709 * a GL buffer object but does not have an existing data store or 1710 * the size of the buffer is 0." 1711 */ 1712 if (!buf || buf->Size == 0) { 1713 mtx_unlock(&ctx->Shared->Mutex); 1714 return MESA_GLINTEROP_INVALID_OBJECT; 1715 } 1716 1717 res = st_buffer_object(buf)->buffer; 1718 if (!res) { 1719 /* this shouldn't happen */ 1720 mtx_unlock(&ctx->Shared->Mutex); 1721 return MESA_GLINTEROP_INVALID_OBJECT; 1722 } 1723 1724 out->buf_offset = 0; 1725 out->buf_size = buf->Size; 1726 1727 buf->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; 1728 } else if (target == GL_RENDERBUFFER) { 1729 /* Renderbuffers. 1730 * 1731 * The error checking is based on the documentation of 1732 * clCreateFromGLRenderbuffer from OpenCL 2.0 SDK. 1733 */ 1734 struct gl_renderbuffer *rb = _mesa_lookup_renderbuffer(ctx, in->obj); 1735 1736 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: 1737 * "CL_INVALID_GL_OBJECT if renderbuffer is not a GL renderbuffer 1738 * object or if the width or height of renderbuffer is zero." 1739 */ 1740 if (!rb || rb->Width == 0 || rb->Height == 0) { 1741 mtx_unlock(&ctx->Shared->Mutex); 1742 return MESA_GLINTEROP_INVALID_OBJECT; 1743 } 1744 1745 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: 1746 * "CL_INVALID_OPERATION if renderbuffer is a multi-sample GL 1747 * renderbuffer object." 1748 */ 1749 if (rb->NumSamples > 1) { 1750 mtx_unlock(&ctx->Shared->Mutex); 1751 return MESA_GLINTEROP_INVALID_OPERATION; 1752 } 1753 1754 /* From OpenCL 2.0 SDK, clCreateFromGLRenderbuffer: 1755 * "CL_OUT_OF_RESOURCES if there is a failure to allocate resources 1756 * required by the OpenCL implementation on the device." 1757 */ 1758 res = st_renderbuffer(rb)->texture; 1759 if (!res) { 1760 mtx_unlock(&ctx->Shared->Mutex); 1761 return MESA_GLINTEROP_OUT_OF_RESOURCES; 1762 } 1763 1764 out->internal_format = rb->InternalFormat; 1765 out->view_minlevel = 0; 1766 out->view_numlevels = 1; 1767 out->view_minlayer = 0; 1768 out->view_numlayers = 1; 1769 } else { 1770 /* Texture objects. 1771 * 1772 * The error checking is based on the documentation of 1773 * clCreateFromGLTexture from OpenCL 2.0 SDK. 1774 */ 1775 struct gl_texture_object *obj = _mesa_lookup_texture(ctx, in->obj); 1776 1777 if (obj) 1778 _mesa_test_texobj_completeness(ctx, obj); 1779 1780 /* From OpenCL 2.0 SDK, clCreateFromGLTexture: 1781 * "CL_INVALID_GL_OBJECT if texture is not a GL texture object whose 1782 * type matches texture_target, if the specified miplevel of texture 1783 * is not defined, or if the width or height of the specified 1784 * miplevel is zero or if the GL texture object is incomplete." 1785 */ 1786 if (!obj || 1787 obj->Target != target || 1788 !obj->_BaseComplete || 1789 (in->miplevel > 0 && !obj->_MipmapComplete)) { 1790 mtx_unlock(&ctx->Shared->Mutex); 1791 return MESA_GLINTEROP_INVALID_OBJECT; 1792 } 1793 1794 /* From OpenCL 2.0 SDK, clCreateFromGLTexture: 1795 * "CL_INVALID_MIP_LEVEL if miplevel is less than the value of 1796 * levelbase (for OpenGL implementations) or zero (for OpenGL ES 1797 * implementations); or greater than the value of q (for both OpenGL 1798 * and OpenGL ES). levelbase and q are defined for the texture in 1799 * section 3.8.10 (Texture Completeness) of the OpenGL 2.1 1800 * specification and section 3.7.10 of the OpenGL ES 2.0." 1801 */ 1802 if (in->miplevel < obj->BaseLevel || in->miplevel > obj->_MaxLevel) { 1803 mtx_unlock(&ctx->Shared->Mutex); 1804 return MESA_GLINTEROP_INVALID_MIP_LEVEL; 1805 } 1806 1807 if (!st_finalize_texture(ctx, st->pipe, obj, 0)) { 1808 mtx_unlock(&ctx->Shared->Mutex); 1809 return MESA_GLINTEROP_OUT_OF_RESOURCES; 1810 } 1811 1812 res = st_get_texobj_resource(obj); 1813 if (!res) { 1814 /* Incomplete texture buffer object? This shouldn't really occur. */ 1815 mtx_unlock(&ctx->Shared->Mutex); 1816 return MESA_GLINTEROP_INVALID_OBJECT; 1817 } 1818 1819 if (target == GL_TEXTURE_BUFFER) { 1820 out->internal_format = obj->BufferObjectFormat; 1821 out->buf_offset = obj->BufferOffset; 1822 out->buf_size = obj->BufferSize == -1 ? obj->BufferObject->Size : 1823 obj->BufferSize; 1824 1825 obj->BufferObject->UsageHistory |= USAGE_DISABLE_MINMAX_CACHE; 1826 } else { 1827 out->internal_format = obj->Image[0][0]->InternalFormat; 1828 out->view_minlevel = obj->MinLevel; 1829 out->view_numlevels = obj->NumLevels; 1830 out->view_minlayer = obj->MinLayer; 1831 out->view_numlayers = obj->NumLayers; 1832 } 1833 } 1834 1835 /* Get the handle. */ 1836 switch (in->access) { 1837 case MESA_GLINTEROP_ACCESS_READ_WRITE: 1838 usage = PIPE_HANDLE_USAGE_READ_WRITE; 1839 break; 1840 case MESA_GLINTEROP_ACCESS_READ_ONLY: 1841 usage = PIPE_HANDLE_USAGE_READ; 1842 break; 1843 case MESA_GLINTEROP_ACCESS_WRITE_ONLY: 1844 usage = PIPE_HANDLE_USAGE_WRITE; 1845 break; 1846 default: 1847 usage = 0; 1848 } 1849 1850 memset(&whandle, 0, sizeof(whandle)); 1851 whandle.type = DRM_API_HANDLE_TYPE_FD; 1852 1853 success = screen->resource_get_handle(screen, st->pipe, res, &whandle, 1854 usage); 1855 mtx_unlock(&ctx->Shared->Mutex); 1856 1857 if (!success) 1858 return MESA_GLINTEROP_OUT_OF_HOST_MEMORY; 1859 1860 out->dmabuf_fd = whandle.handle; 1861 out->out_driver_data_written = 0; 1862 1863 if (res->target == PIPE_BUFFER) 1864 out->buf_offset += whandle.offset; 1865 1866 /* Instruct the caller that we support up-to version one of the interface */ 1867 in->version = 1; 1868 out->version = 1; 1869 1870 return MESA_GLINTEROP_SUCCESS; 1871} 1872 1873static const __DRI2interopExtension dri2InteropExtension = { 1874 .base = { __DRI2_INTEROP, 1 }, 1875 .query_device_info = dri2_interop_query_device_info, 1876 .export_object = dri2_interop_export_object 1877}; 1878 1879/* 1880 * Backend function init_screen. 1881 */ 1882 1883static const __DRIextension *dri_screen_extensions[] = { 1884 &driTexBufferExtension.base, 1885 &dri2FlushExtension.base, 1886 &dri2ImageExtension.base, 1887 &dri2RendererQueryExtension.base, 1888 &dri2ConfigQueryExtension.base, 1889 &dri2ThrottleExtension.base, 1890 &dri2FenceExtension.base, 1891 &dri2InteropExtension.base, 1892 NULL 1893}; 1894 1895static const __DRIextension *dri_robust_screen_extensions[] = { 1896 &driTexBufferExtension.base, 1897 &dri2FlushExtension.base, 1898 &dri2ImageExtension.base, 1899 &dri2RendererQueryExtension.base, 1900 &dri2ConfigQueryExtension.base, 1901 &dri2ThrottleExtension.base, 1902 &dri2FenceExtension.base, 1903 &dri2InteropExtension.base, 1904 &dri2Robustness.base, 1905 NULL 1906}; 1907 1908/** 1909 * This is the driver specific part of the createNewScreen entry point. 1910 * 1911 * Returns the struct gl_config supported by this driver. 1912 */ 1913static const __DRIconfig ** 1914dri2_init_screen(__DRIscreen * sPriv) 1915{ 1916 const __DRIconfig **configs; 1917 struct dri_screen *screen; 1918 struct pipe_screen *pscreen = NULL; 1919 const struct drm_conf_ret *throttle_ret; 1920 const struct drm_conf_ret *dmabuf_ret; 1921 int fd; 1922 1923 screen = CALLOC_STRUCT(dri_screen); 1924 if (!screen) 1925 return NULL; 1926 1927 screen->sPriv = sPriv; 1928 screen->fd = sPriv->fd; 1929 pipe_mutex_init(screen->opencl_func_mutex); 1930 1931 sPriv->driverPrivate = (void *)screen; 1932 1933 if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0) 1934 goto free_screen; 1935 1936 if (pipe_loader_drm_probe_fd(&screen->dev, fd)) 1937 pscreen = pipe_loader_create_screen(screen->dev); 1938 1939 if (!pscreen) 1940 goto release_pipe; 1941 1942 throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE); 1943 dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD); 1944 1945 if (throttle_ret && throttle_ret->val.val_int != -1) { 1946 screen->throttling_enabled = TRUE; 1947 screen->default_throttle_frames = throttle_ret->val.val_int; 1948 } 1949 1950 if (dmabuf_ret && dmabuf_ret->val.val_bool) { 1951 uint64_t cap; 1952 1953 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && 1954 (cap & DRM_PRIME_CAP_IMPORT)) { 1955 dri2ImageExtension.createImageFromFds = dri2_from_fds; 1956 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; 1957 } 1958 } 1959 1960 if (pscreen->get_param(pscreen, PIPE_CAP_DEVICE_RESET_STATUS_QUERY)) { 1961 sPriv->extensions = dri_robust_screen_extensions; 1962 screen->has_reset_status_query = true; 1963 } 1964 else 1965 sPriv->extensions = dri_screen_extensions; 1966 1967 configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name); 1968 if (!configs) 1969 goto destroy_screen; 1970 1971 screen->can_share_buffer = true; 1972 screen->auto_fake_front = dri_with_format(sPriv); 1973 screen->broken_invalidate = !sPriv->dri2.useInvalidate; 1974 screen->lookup_egl_image = dri2_lookup_egl_image; 1975 1976 return configs; 1977 1978destroy_screen: 1979 dri_destroy_screen_helper(screen); 1980 1981release_pipe: 1982 if (screen->dev) 1983 pipe_loader_release(&screen->dev, 1); 1984 else 1985 close(fd); 1986 1987free_screen: 1988 FREE(screen); 1989 return NULL; 1990} 1991 1992/** 1993 * This is the driver specific part of the createNewScreen entry point. 1994 * 1995 * Returns the struct gl_config supported by this driver. 1996 */ 1997static const __DRIconfig ** 1998dri_kms_init_screen(__DRIscreen * sPriv) 1999{ 2000#if defined(GALLIUM_SOFTPIPE) 2001 const __DRIconfig **configs; 2002 struct dri_screen *screen; 2003 struct pipe_screen *pscreen = NULL; 2004 uint64_t cap; 2005 int fd; 2006 2007 screen = CALLOC_STRUCT(dri_screen); 2008 if (!screen) 2009 return NULL; 2010 2011 screen->sPriv = sPriv; 2012 screen->fd = sPriv->fd; 2013 2014 sPriv->driverPrivate = (void *)screen; 2015 2016 if (screen->fd < 0 || (fd = fcntl(screen->fd, F_DUPFD_CLOEXEC, 3)) < 0) 2017 goto free_screen; 2018 2019 if (pipe_loader_sw_probe_kms(&screen->dev, fd)) 2020 pscreen = pipe_loader_create_screen(screen->dev); 2021 2022 if (!pscreen) 2023 goto release_pipe; 2024 2025 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && 2026 (cap & DRM_PRIME_CAP_IMPORT)) { 2027 dri2ImageExtension.createImageFromFds = dri2_from_fds; 2028 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; 2029 } 2030 2031 sPriv->extensions = dri_screen_extensions; 2032 2033 configs = dri_init_screen_helper(screen, pscreen, "swrast"); 2034 if (!configs) 2035 goto destroy_screen; 2036 2037 screen->can_share_buffer = false; 2038 screen->auto_fake_front = dri_with_format(sPriv); 2039 screen->broken_invalidate = !sPriv->dri2.useInvalidate; 2040 screen->lookup_egl_image = dri2_lookup_egl_image; 2041 2042 return configs; 2043 2044destroy_screen: 2045 dri_destroy_screen_helper(screen); 2046 2047release_pipe: 2048 if (screen->dev) 2049 pipe_loader_release(&screen->dev, 1); 2050 else 2051 close(fd); 2052 2053free_screen: 2054 FREE(screen); 2055#endif // GALLIUM_SOFTPIPE 2056 return NULL; 2057} 2058 2059static boolean 2060dri2_create_buffer(__DRIscreen * sPriv, 2061 __DRIdrawable * dPriv, 2062 const struct gl_config * visual, boolean isPixmap) 2063{ 2064 struct dri_drawable *drawable = NULL; 2065 2066 if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) 2067 return FALSE; 2068 2069 drawable = dPriv->driverPrivate; 2070 2071 drawable->allocate_textures = dri2_allocate_textures; 2072 drawable->flush_frontbuffer = dri2_flush_frontbuffer; 2073 drawable->update_tex_buffer = dri2_update_tex_buffer; 2074 2075 return TRUE; 2076} 2077 2078/** 2079 * DRI driver virtual function table. 2080 * 2081 * DRI versions differ in their implementation of init_screen and swap_buffers. 2082 */ 2083const struct __DriverAPIRec galliumdrm_driver_api = { 2084 .InitScreen = dri2_init_screen, 2085 .DestroyScreen = dri_destroy_screen, 2086 .CreateContext = dri_create_context, 2087 .DestroyContext = dri_destroy_context, 2088 .CreateBuffer = dri2_create_buffer, 2089 .DestroyBuffer = dri_destroy_buffer, 2090 .MakeCurrent = dri_make_current, 2091 .UnbindContext = dri_unbind_context, 2092 2093 .AllocateBuffer = dri2_allocate_buffer, 2094 .ReleaseBuffer = dri2_release_buffer, 2095}; 2096 2097/** 2098 * DRI driver virtual function table. 2099 * 2100 * KMS/DRM version of the DriverAPI above sporting a different InitScreen 2101 * hook. The latter is used to explicitly initialise the kms_swrast driver 2102 * rather than selecting the approapriate driver as suggested by the loader. 2103 */ 2104const struct __DriverAPIRec dri_kms_driver_api = { 2105 .InitScreen = dri_kms_init_screen, 2106 .DestroyScreen = dri_destroy_screen, 2107 .CreateContext = dri_create_context, 2108 .DestroyContext = dri_destroy_context, 2109 .CreateBuffer = dri2_create_buffer, 2110 .DestroyBuffer = dri_destroy_buffer, 2111 .MakeCurrent = dri_make_current, 2112 .UnbindContext = dri_unbind_context, 2113 2114 .AllocateBuffer = dri2_allocate_buffer, 2115 .ReleaseBuffer = dri2_release_buffer, 2116}; 2117 2118/* This is the table of extensions that the loader will dlsym() for. */ 2119const __DRIextension *galliumdrm_driver_extensions[] = { 2120 &driCoreExtension.base, 2121 &driImageDriverExtension.base, 2122 &driDRI2Extension.base, 2123 &gallium_config_options.base, 2124 &dri2FenceExtension.base, 2125 NULL 2126}; 2127 2128/* vim: set sw=3 ts=8 sts=3 expandtab: */ 2129