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