dri2.c revision 848b8605
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 "util/u_memory.h" 33#include "util/u_inlines.h" 34#include "util/u_format.h" 35#include "util/u_debug.h" 36#include "state_tracker/drm_driver.h" 37#include "state_tracker/st_texture.h" 38#include "state_tracker/st_context.h" 39#include "pipe-loader/pipe_loader.h" 40#include "main/texobj.h" 41 42#include "dri_screen.h" 43#include "dri_context.h" 44#include "dri_drawable.h" 45#include "dri_query_renderer.h" 46#include "dri2_buffer.h" 47 48static int convert_fourcc(int format, int *dri_components_p) 49{ 50 int dri_components; 51 switch(format) { 52 case __DRI_IMAGE_FOURCC_RGB565: 53 format = __DRI_IMAGE_FORMAT_RGB565; 54 dri_components = __DRI_IMAGE_COMPONENTS_RGB; 55 break; 56 case __DRI_IMAGE_FOURCC_ARGB8888: 57 format = __DRI_IMAGE_FORMAT_ARGB8888; 58 dri_components = __DRI_IMAGE_COMPONENTS_RGBA; 59 break; 60 case __DRI_IMAGE_FOURCC_XRGB8888: 61 format = __DRI_IMAGE_FORMAT_XRGB8888; 62 dri_components = __DRI_IMAGE_COMPONENTS_RGB; 63 break; 64 case __DRI_IMAGE_FOURCC_ABGR8888: 65 format = __DRI_IMAGE_FORMAT_ABGR8888; 66 dri_components = __DRI_IMAGE_COMPONENTS_RGBA; 67 break; 68 case __DRI_IMAGE_FOURCC_XBGR8888: 69 format = __DRI_IMAGE_FORMAT_XBGR8888; 70 dri_components = __DRI_IMAGE_COMPONENTS_RGB; 71 break; 72 default: 73 return -1; 74 } 75 *dri_components_p = dri_components; 76 return format; 77} 78 79/** 80 * DRI2 flush extension. 81 */ 82static void 83dri2_flush_drawable(__DRIdrawable *dPriv) 84{ 85 dri_flush(dPriv->driContextPriv, dPriv, __DRI2_FLUSH_DRAWABLE, -1); 86} 87 88static void 89dri2_invalidate_drawable(__DRIdrawable *dPriv) 90{ 91 struct dri_drawable *drawable = dri_drawable(dPriv); 92 93 dri2InvalidateDrawable(dPriv); 94 drawable->dPriv->lastStamp = drawable->dPriv->dri2.stamp; 95 96 p_atomic_inc(&drawable->base.stamp); 97} 98 99static const __DRI2flushExtension dri2FlushExtension = { 100 .base = { __DRI2_FLUSH, 4 }, 101 102 .flush = dri2_flush_drawable, 103 .invalidate = dri2_invalidate_drawable, 104 .flush_with_flags = dri_flush, 105}; 106 107/** 108 * Retrieve __DRIbuffer from the DRI loader. 109 */ 110static __DRIbuffer * 111dri2_drawable_get_buffers(struct dri_drawable *drawable, 112 const enum st_attachment_type *atts, 113 unsigned *count) 114{ 115 __DRIdrawable *dri_drawable = drawable->dPriv; 116 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; 117 boolean with_format; 118 __DRIbuffer *buffers; 119 int num_buffers; 120 unsigned attachments[10]; 121 unsigned num_attachments, i; 122 123 assert(loader); 124 with_format = dri_with_format(drawable->sPriv); 125 126 num_attachments = 0; 127 128 /* for Xserver 1.6.0 (DRI2 version 1) we always need to ask for the front */ 129 if (!with_format) 130 attachments[num_attachments++] = __DRI_BUFFER_FRONT_LEFT; 131 132 for (i = 0; i < *count; i++) { 133 enum pipe_format format; 134 unsigned bind; 135 int att, depth; 136 137 dri_drawable_get_format(drawable, atts[i], &format, &bind); 138 if (format == PIPE_FORMAT_NONE) 139 continue; 140 141 switch (atts[i]) { 142 case ST_ATTACHMENT_FRONT_LEFT: 143 /* already added */ 144 if (!with_format) 145 continue; 146 att = __DRI_BUFFER_FRONT_LEFT; 147 break; 148 case ST_ATTACHMENT_BACK_LEFT: 149 att = __DRI_BUFFER_BACK_LEFT; 150 break; 151 case ST_ATTACHMENT_FRONT_RIGHT: 152 att = __DRI_BUFFER_FRONT_RIGHT; 153 break; 154 case ST_ATTACHMENT_BACK_RIGHT: 155 att = __DRI_BUFFER_BACK_RIGHT; 156 break; 157 default: 158 continue; 159 } 160 161 /* 162 * In this switch statement we must support all formats that 163 * may occur as the stvis->color_format. 164 */ 165 switch(format) { 166 case PIPE_FORMAT_B8G8R8A8_UNORM: 167 depth = 32; 168 break; 169 case PIPE_FORMAT_B8G8R8X8_UNORM: 170 depth = 24; 171 break; 172 case PIPE_FORMAT_B5G6R5_UNORM: 173 depth = 16; 174 break; 175 default: 176 depth = util_format_get_blocksizebits(format); 177 assert(!"Unexpected format in dri2_drawable_get_buffers()"); 178 } 179 180 attachments[num_attachments++] = att; 181 if (with_format) { 182 attachments[num_attachments++] = depth; 183 } 184 } 185 186 if (with_format) { 187 num_attachments /= 2; 188 buffers = loader->getBuffersWithFormat(dri_drawable, 189 &dri_drawable->w, &dri_drawable->h, 190 attachments, num_attachments, 191 &num_buffers, dri_drawable->loaderPrivate); 192 } 193 else { 194 buffers = loader->getBuffers(dri_drawable, 195 &dri_drawable->w, &dri_drawable->h, 196 attachments, num_attachments, 197 &num_buffers, dri_drawable->loaderPrivate); 198 } 199 200 if (buffers) 201 *count = num_buffers; 202 203 return buffers; 204} 205 206static bool 207dri_image_drawable_get_buffers(struct dri_drawable *drawable, 208 struct __DRIimageList *images, 209 const enum st_attachment_type *statts, 210 unsigned statts_count) 211{ 212 __DRIdrawable *dPriv = drawable->dPriv; 213 __DRIscreen *sPriv = drawable->sPriv; 214 unsigned int image_format = __DRI_IMAGE_FORMAT_NONE; 215 enum pipe_format pf; 216 uint32_t buffer_mask = 0; 217 unsigned i, bind; 218 219 for (i = 0; i < statts_count; i++) { 220 dri_drawable_get_format(drawable, statts[i], &pf, &bind); 221 if (pf == PIPE_FORMAT_NONE) 222 continue; 223 224 switch (statts[i]) { 225 case ST_ATTACHMENT_FRONT_LEFT: 226 buffer_mask |= __DRI_IMAGE_BUFFER_FRONT; 227 break; 228 case ST_ATTACHMENT_BACK_LEFT: 229 buffer_mask |= __DRI_IMAGE_BUFFER_BACK; 230 break; 231 default: 232 continue; 233 } 234 235 switch (pf) { 236 case PIPE_FORMAT_B5G6R5_UNORM: 237 image_format = __DRI_IMAGE_FORMAT_RGB565; 238 break; 239 case PIPE_FORMAT_B8G8R8X8_UNORM: 240 image_format = __DRI_IMAGE_FORMAT_XRGB8888; 241 break; 242 case PIPE_FORMAT_B8G8R8A8_UNORM: 243 image_format = __DRI_IMAGE_FORMAT_ARGB8888; 244 break; 245 case PIPE_FORMAT_R8G8B8A8_UNORM: 246 image_format = __DRI_IMAGE_FORMAT_ABGR8888; 247 break; 248 default: 249 image_format = __DRI_IMAGE_FORMAT_NONE; 250 break; 251 } 252 } 253 254 return (*sPriv->image.loader->getBuffers) (dPriv, image_format, 255 (uint32_t *) &drawable->base.stamp, 256 dPriv->loaderPrivate, buffer_mask, 257 images); 258} 259 260static __DRIbuffer * 261dri2_allocate_buffer(__DRIscreen *sPriv, 262 unsigned attachment, unsigned format, 263 int width, int height) 264{ 265 struct dri_screen *screen = dri_screen(sPriv); 266 struct dri2_buffer *buffer; 267 struct pipe_resource templ; 268 enum pipe_format pf; 269 unsigned bind = 0; 270 struct winsys_handle whandle; 271 272 switch (attachment) { 273 case __DRI_BUFFER_FRONT_LEFT: 274 case __DRI_BUFFER_FAKE_FRONT_LEFT: 275 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 276 break; 277 case __DRI_BUFFER_BACK_LEFT: 278 bind = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 279 break; 280 case __DRI_BUFFER_DEPTH: 281 case __DRI_BUFFER_DEPTH_STENCIL: 282 case __DRI_BUFFER_STENCIL: 283 bind = PIPE_BIND_DEPTH_STENCIL; /* XXX sampler? */ 284 break; 285 } 286 287 /* because we get the handle and stride */ 288 bind |= PIPE_BIND_SHARED; 289 290 switch (format) { 291 case 32: 292 pf = PIPE_FORMAT_B8G8R8A8_UNORM; 293 break; 294 case 24: 295 pf = PIPE_FORMAT_B8G8R8X8_UNORM; 296 break; 297 case 16: 298 pf = PIPE_FORMAT_Z16_UNORM; 299 break; 300 default: 301 return NULL; 302 } 303 304 buffer = CALLOC_STRUCT(dri2_buffer); 305 if (!buffer) 306 return NULL; 307 308 memset(&templ, 0, sizeof(templ)); 309 templ.bind = bind; 310 templ.format = pf; 311 templ.target = PIPE_TEXTURE_2D; 312 templ.last_level = 0; 313 templ.width0 = width; 314 templ.height0 = height; 315 templ.depth0 = 1; 316 templ.array_size = 1; 317 318 buffer->resource = 319 screen->base.screen->resource_create(screen->base.screen, &templ); 320 if (!buffer->resource) { 321 FREE(buffer); 322 return NULL; 323 } 324 325 memset(&whandle, 0, sizeof(whandle)); 326 if (screen->can_share_buffer) 327 whandle.type = DRM_API_HANDLE_TYPE_SHARED; 328 else 329 whandle.type = DRM_API_HANDLE_TYPE_KMS; 330 331 screen->base.screen->resource_get_handle(screen->base.screen, 332 buffer->resource, &whandle); 333 334 buffer->base.attachment = attachment; 335 buffer->base.name = whandle.handle; 336 buffer->base.cpp = util_format_get_blocksize(pf); 337 buffer->base.pitch = whandle.stride; 338 339 return &buffer->base; 340} 341 342static void 343dri2_release_buffer(__DRIscreen *sPriv, __DRIbuffer *bPriv) 344{ 345 struct dri2_buffer *buffer = dri2_buffer(bPriv); 346 347 pipe_resource_reference(&buffer->resource, NULL); 348 FREE(buffer); 349} 350 351/* 352 * Backend functions for st_framebuffer interface. 353 */ 354 355static void 356dri2_allocate_textures(struct dri_context *ctx, 357 struct dri_drawable *drawable, 358 const enum st_attachment_type *statts, 359 unsigned statts_count) 360{ 361 __DRIscreen *sPriv = drawable->sPriv; 362 __DRIdrawable *dri_drawable = drawable->dPriv; 363 struct dri_screen *screen = dri_screen(sPriv); 364 struct pipe_resource templ; 365 boolean alloc_depthstencil = FALSE; 366 unsigned i, j, bind; 367 const __DRIimageLoaderExtension *image = sPriv->image.loader; 368 /* Image specific variables */ 369 struct __DRIimageList images; 370 /* Dri2 specific variables */ 371 __DRIbuffer *buffers; 372 struct winsys_handle whandle; 373 unsigned num_buffers = statts_count; 374 375 /* First get the buffers from the loader */ 376 if (image) { 377 if (!dri_image_drawable_get_buffers(drawable, &images, 378 statts, statts_count)) 379 return; 380 } 381 else { 382 buffers = dri2_drawable_get_buffers(drawable, statts, &num_buffers); 383 if (!buffers || (drawable->old_num == num_buffers && 384 drawable->old_w == dri_drawable->w && 385 drawable->old_h == dri_drawable->h && 386 memcmp(drawable->old, buffers, 387 sizeof(__DRIbuffer) * num_buffers) == 0)) 388 return; 389 } 390 391 /* Second clean useless resources*/ 392 393 /* See if we need a depth-stencil buffer. */ 394 for (i = 0; i < statts_count; i++) { 395 if (statts[i] == ST_ATTACHMENT_DEPTH_STENCIL) { 396 alloc_depthstencil = TRUE; 397 break; 398 } 399 } 400 401 /* Delete the resources we won't need. */ 402 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 403 /* Don't delete the depth-stencil buffer, we can reuse it. */ 404 if (i == ST_ATTACHMENT_DEPTH_STENCIL && alloc_depthstencil) 405 continue; 406 407 /* Flush the texture before unreferencing, so that other clients can 408 * see what the driver has rendered. 409 */ 410 if (i != ST_ATTACHMENT_DEPTH_STENCIL && drawable->textures[i]) { 411 struct pipe_context *pipe = ctx->st->pipe; 412 pipe->flush_resource(pipe, drawable->textures[i]); 413 } 414 415 pipe_resource_reference(&drawable->textures[i], NULL); 416 } 417 418 if (drawable->stvis.samples > 1) { 419 for (i = 0; i < ST_ATTACHMENT_COUNT; i++) { 420 boolean del = TRUE; 421 422 /* Don't delete MSAA resources for the attachments which are enabled, 423 * we can reuse them. */ 424 for (j = 0; j < statts_count; j++) { 425 if (i == statts[j]) { 426 del = FALSE; 427 break; 428 } 429 } 430 431 if (del) { 432 pipe_resource_reference(&drawable->msaa_textures[i], NULL); 433 } 434 } 435 } 436 437 /* Third use the buffers retrieved to fill the drawable info */ 438 439 memset(&templ, 0, sizeof(templ)); 440 templ.target = screen->target; 441 templ.last_level = 0; 442 templ.depth0 = 1; 443 templ.array_size = 1; 444 445 if (image) { 446 if (images.image_mask & __DRI_IMAGE_BUFFER_FRONT) { 447 struct pipe_resource **buf = 448 &drawable->textures[ST_ATTACHMENT_FRONT_LEFT]; 449 struct pipe_resource *texture = images.front->texture; 450 451 dri_drawable->w = texture->width0; 452 dri_drawable->h = texture->height0; 453 454 pipe_resource_reference(buf, texture); 455 } 456 457 if (images.image_mask & __DRI_IMAGE_BUFFER_BACK) { 458 struct pipe_resource **buf = 459 &drawable->textures[ST_ATTACHMENT_BACK_LEFT]; 460 struct pipe_resource *texture = images.back->texture; 461 462 dri_drawable->w = texture->width0; 463 dri_drawable->h = texture->height0; 464 465 pipe_resource_reference(buf, texture); 466 } 467 468 /* Note: if there is both a back and a front buffer, 469 * then they have the same size. 470 */ 471 templ.width0 = dri_drawable->w; 472 templ.height0 = dri_drawable->h; 473 } 474 else { 475 memset(&whandle, 0, sizeof(whandle)); 476 477 /* Process DRI-provided buffers and get pipe_resources. */ 478 for (i = 0; i < num_buffers; i++) { 479 __DRIbuffer *buf = &buffers[i]; 480 enum st_attachment_type statt; 481 enum pipe_format format; 482 483 switch (buf->attachment) { 484 case __DRI_BUFFER_FRONT_LEFT: 485 if (!screen->auto_fake_front) { 486 continue; /* invalid attachment */ 487 } 488 /* fallthrough */ 489 case __DRI_BUFFER_FAKE_FRONT_LEFT: 490 statt = ST_ATTACHMENT_FRONT_LEFT; 491 break; 492 case __DRI_BUFFER_BACK_LEFT: 493 statt = ST_ATTACHMENT_BACK_LEFT; 494 break; 495 default: 496 continue; /* invalid attachment */ 497 } 498 499 dri_drawable_get_format(drawable, statt, &format, &bind); 500 if (format == PIPE_FORMAT_NONE) 501 continue; 502 503 /* dri2_drawable_get_buffers has already filled dri_drawable->w 504 * and dri_drawable->h */ 505 templ.width0 = dri_drawable->w; 506 templ.height0 = dri_drawable->h; 507 templ.format = format; 508 templ.bind = bind; 509 whandle.handle = buf->name; 510 whandle.stride = buf->pitch; 511 if (screen->can_share_buffer) 512 whandle.type = DRM_API_HANDLE_TYPE_SHARED; 513 else 514 whandle.type = DRM_API_HANDLE_TYPE_KMS; 515 drawable->textures[statt] = 516 screen->base.screen->resource_from_handle(screen->base.screen, 517 &templ, &whandle); 518 assert(drawable->textures[statt]); 519 } 520 } 521 522 /* Allocate private MSAA colorbuffers. */ 523 if (drawable->stvis.samples > 1) { 524 for (i = 0; i < statts_count; i++) { 525 enum st_attachment_type statt = statts[i]; 526 527 if (statt == ST_ATTACHMENT_DEPTH_STENCIL) 528 continue; 529 530 if (drawable->textures[statt]) { 531 templ.format = drawable->textures[statt]->format; 532 templ.bind = drawable->textures[statt]->bind; 533 templ.nr_samples = drawable->stvis.samples; 534 535 /* Try to reuse the resource. 536 * (the other resource parameters should be constant) 537 */ 538 if (!drawable->msaa_textures[statt] || 539 drawable->msaa_textures[statt]->width0 != templ.width0 || 540 drawable->msaa_textures[statt]->height0 != templ.height0) { 541 /* Allocate a new one. */ 542 pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 543 544 drawable->msaa_textures[statt] = 545 screen->base.screen->resource_create(screen->base.screen, 546 &templ); 547 assert(drawable->msaa_textures[statt]); 548 549 /* If there are any MSAA resources, we should initialize them 550 * such that they contain the same data as the single-sample 551 * resources we just got from the X server. 552 * 553 * The reason for this is that the state tracker (and 554 * therefore the app) can access the MSAA resources only. 555 * The single-sample resources are not exposed 556 * to the state tracker. 557 * 558 */ 559 dri_pipe_blit(ctx->st->pipe, 560 drawable->msaa_textures[statt], 561 drawable->textures[statt]); 562 } 563 } 564 else { 565 pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 566 } 567 } 568 } 569 570 /* Allocate a private depth-stencil buffer. */ 571 if (alloc_depthstencil) { 572 enum st_attachment_type statt = ST_ATTACHMENT_DEPTH_STENCIL; 573 struct pipe_resource **zsbuf; 574 enum pipe_format format; 575 unsigned bind; 576 577 dri_drawable_get_format(drawable, statt, &format, &bind); 578 579 if (format) { 580 templ.format = format; 581 templ.bind = bind; 582 583 if (drawable->stvis.samples > 1) { 584 templ.nr_samples = drawable->stvis.samples; 585 zsbuf = &drawable->msaa_textures[statt]; 586 } 587 else { 588 templ.nr_samples = 0; 589 zsbuf = &drawable->textures[statt]; 590 } 591 592 /* Try to reuse the resource. 593 * (the other resource parameters should be constant) 594 */ 595 if (!*zsbuf || 596 (*zsbuf)->width0 != templ.width0 || 597 (*zsbuf)->height0 != templ.height0) { 598 /* Allocate a new one. */ 599 pipe_resource_reference(zsbuf, NULL); 600 *zsbuf = screen->base.screen->resource_create(screen->base.screen, 601 &templ); 602 assert(*zsbuf); 603 } 604 } 605 else { 606 pipe_resource_reference(&drawable->msaa_textures[statt], NULL); 607 pipe_resource_reference(&drawable->textures[statt], NULL); 608 } 609 } 610 611 /* For DRI2, we may get the same buffers again from the server. 612 * To prevent useless imports of gem names, drawable->old* is used 613 * to bypass the import if we get the same buffers. This doesn't apply 614 * to DRI3/Wayland, users of image.loader, since the buffer is managed 615 * by the client (no import), and the back buffer is going to change 616 * at every redraw. 617 */ 618 if (!image) { 619 drawable->old_num = num_buffers; 620 drawable->old_w = dri_drawable->w; 621 drawable->old_h = dri_drawable->h; 622 memcpy(drawable->old, buffers, sizeof(__DRIbuffer) * num_buffers); 623 } 624} 625 626static void 627dri2_flush_frontbuffer(struct dri_context *ctx, 628 struct dri_drawable *drawable, 629 enum st_attachment_type statt) 630{ 631 __DRIdrawable *dri_drawable = drawable->dPriv; 632 const __DRIimageLoaderExtension *image = drawable->sPriv->image.loader; 633 const __DRIdri2LoaderExtension *loader = drawable->sPriv->dri2.loader; 634 struct pipe_context *pipe = ctx->st->pipe; 635 636 if (statt != ST_ATTACHMENT_FRONT_LEFT) 637 return; 638 639 if (drawable->stvis.samples > 1) { 640 /* Resolve the front buffer. */ 641 dri_pipe_blit(ctx->st->pipe, 642 drawable->textures[ST_ATTACHMENT_FRONT_LEFT], 643 drawable->msaa_textures[ST_ATTACHMENT_FRONT_LEFT]); 644 } 645 646 if (drawable->textures[ST_ATTACHMENT_FRONT_LEFT]) { 647 pipe->flush_resource(pipe, drawable->textures[ST_ATTACHMENT_FRONT_LEFT]); 648 } 649 650 pipe->flush(pipe, NULL, 0); 651 652 if (image) { 653 image->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); 654 } 655 else if (loader->flushFrontBuffer) { 656 loader->flushFrontBuffer(dri_drawable, dri_drawable->loaderPrivate); 657 } 658} 659 660static void 661dri2_update_tex_buffer(struct dri_drawable *drawable, 662 struct dri_context *ctx, 663 struct pipe_resource *res) 664{ 665 /* no-op */ 666} 667 668static __DRIimage * 669dri2_lookup_egl_image(struct dri_screen *screen, void *handle) 670{ 671 const __DRIimageLookupExtension *loader = screen->sPriv->dri2.image; 672 __DRIimage *img; 673 674 if (!loader->lookupEGLImage) 675 return NULL; 676 677 img = loader->lookupEGLImage(screen->sPriv, 678 handle, screen->sPriv->loaderPrivate); 679 680 return img; 681} 682 683static __DRIimage * 684dri2_create_image_from_winsys(__DRIscreen *_screen, 685 int width, int height, int format, 686 struct winsys_handle *whandle, int pitch, 687 void *loaderPrivate) 688{ 689 struct dri_screen *screen = dri_screen(_screen); 690 __DRIimage *img; 691 struct pipe_resource templ; 692 unsigned tex_usage; 693 enum pipe_format pf; 694 695 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 696 697 switch (format) { 698 case __DRI_IMAGE_FORMAT_RGB565: 699 pf = PIPE_FORMAT_B5G6R5_UNORM; 700 break; 701 case __DRI_IMAGE_FORMAT_XRGB8888: 702 pf = PIPE_FORMAT_B8G8R8X8_UNORM; 703 break; 704 case __DRI_IMAGE_FORMAT_ARGB8888: 705 pf = PIPE_FORMAT_B8G8R8A8_UNORM; 706 break; 707 case __DRI_IMAGE_FORMAT_ABGR8888: 708 pf = PIPE_FORMAT_R8G8B8A8_UNORM; 709 break; 710 default: 711 pf = PIPE_FORMAT_NONE; 712 break; 713 } 714 if (pf == PIPE_FORMAT_NONE) 715 return NULL; 716 717 img = CALLOC_STRUCT(__DRIimageRec); 718 if (!img) 719 return NULL; 720 721 memset(&templ, 0, sizeof(templ)); 722 templ.bind = tex_usage; 723 templ.format = pf; 724 templ.target = screen->target; 725 templ.last_level = 0; 726 templ.width0 = width; 727 templ.height0 = height; 728 templ.depth0 = 1; 729 templ.array_size = 1; 730 731 whandle->stride = pitch * util_format_get_blocksize(pf); 732 733 img->texture = screen->base.screen->resource_from_handle(screen->base.screen, 734 &templ, whandle); 735 if (!img->texture) { 736 FREE(img); 737 return NULL; 738 } 739 740 img->level = 0; 741 img->layer = 0; 742 img->dri_format = format; 743 img->loader_private = loaderPrivate; 744 745 return img; 746} 747 748static __DRIimage * 749dri2_create_image_from_name(__DRIscreen *_screen, 750 int width, int height, int format, 751 int name, int pitch, void *loaderPrivate) 752{ 753 struct winsys_handle whandle; 754 755 memset(&whandle, 0, sizeof(whandle)); 756 whandle.type = DRM_API_HANDLE_TYPE_SHARED; 757 whandle.handle = name; 758 759 return dri2_create_image_from_winsys(_screen, width, height, format, 760 &whandle, pitch, loaderPrivate); 761} 762 763static __DRIimage * 764dri2_create_image_from_fd(__DRIscreen *_screen, 765 int width, int height, int format, 766 int fd, int pitch, void *loaderPrivate) 767{ 768 struct winsys_handle whandle; 769 770 if (fd < 0) 771 return NULL; 772 773 memset(&whandle, 0, sizeof(whandle)); 774 whandle.type = DRM_API_HANDLE_TYPE_FD; 775 whandle.handle = (unsigned)fd; 776 777 return dri2_create_image_from_winsys(_screen, width, height, format, 778 &whandle, pitch, loaderPrivate); 779} 780 781static __DRIimage * 782dri2_create_image_from_renderbuffer(__DRIcontext *context, 783 int renderbuffer, void *loaderPrivate) 784{ 785 struct dri_context *ctx = dri_context(context); 786 787 if (!ctx->st->get_resource_for_egl_image) 788 return NULL; 789 790 /* TODO */ 791 return NULL; 792} 793 794static __DRIimage * 795dri2_create_image(__DRIscreen *_screen, 796 int width, int height, int format, 797 unsigned int use, void *loaderPrivate) 798{ 799 struct dri_screen *screen = dri_screen(_screen); 800 __DRIimage *img; 801 struct pipe_resource templ; 802 unsigned tex_usage; 803 enum pipe_format pf; 804 805 tex_usage = PIPE_BIND_RENDER_TARGET | PIPE_BIND_SAMPLER_VIEW; 806 if (use & __DRI_IMAGE_USE_SCANOUT) 807 tex_usage |= PIPE_BIND_SCANOUT; 808 if (use & __DRI_IMAGE_USE_SHARE) 809 tex_usage |= PIPE_BIND_SHARED; 810 if (use & __DRI_IMAGE_USE_LINEAR) 811 tex_usage |= PIPE_BIND_LINEAR; 812 if (use & __DRI_IMAGE_USE_CURSOR) { 813 if (width != 64 || height != 64) 814 return NULL; 815 tex_usage |= PIPE_BIND_CURSOR; 816 } 817 818 switch (format) { 819 case __DRI_IMAGE_FORMAT_RGB565: 820 pf = PIPE_FORMAT_B5G6R5_UNORM; 821 break; 822 case __DRI_IMAGE_FORMAT_XRGB8888: 823 pf = PIPE_FORMAT_B8G8R8X8_UNORM; 824 break; 825 case __DRI_IMAGE_FORMAT_ARGB8888: 826 pf = PIPE_FORMAT_B8G8R8A8_UNORM; 827 break; 828 case __DRI_IMAGE_FORMAT_ABGR8888: 829 pf = PIPE_FORMAT_R8G8B8A8_UNORM; 830 break; 831 default: 832 pf = PIPE_FORMAT_NONE; 833 break; 834 } 835 if (pf == PIPE_FORMAT_NONE) 836 return NULL; 837 838 img = CALLOC_STRUCT(__DRIimageRec); 839 if (!img) 840 return NULL; 841 842 memset(&templ, 0, sizeof(templ)); 843 templ.bind = tex_usage; 844 templ.format = pf; 845 templ.target = PIPE_TEXTURE_2D; 846 templ.last_level = 0; 847 templ.width0 = width; 848 templ.height0 = height; 849 templ.depth0 = 1; 850 templ.array_size = 1; 851 852 img->texture = screen->base.screen->resource_create(screen->base.screen, &templ); 853 if (!img->texture) { 854 FREE(img); 855 return NULL; 856 } 857 858 img->level = 0; 859 img->layer = 0; 860 img->dri_format = format; 861 img->dri_components = 0; 862 863 img->loader_private = loaderPrivate; 864 return img; 865} 866 867static GLboolean 868dri2_query_image(__DRIimage *image, int attrib, int *value) 869{ 870 struct winsys_handle whandle; 871 memset(&whandle, 0, sizeof(whandle)); 872 873 switch (attrib) { 874 case __DRI_IMAGE_ATTRIB_STRIDE: 875 whandle.type = DRM_API_HANDLE_TYPE_KMS; 876 image->texture->screen->resource_get_handle(image->texture->screen, 877 image->texture, &whandle); 878 *value = whandle.stride; 879 return GL_TRUE; 880 case __DRI_IMAGE_ATTRIB_HANDLE: 881 whandle.type = DRM_API_HANDLE_TYPE_KMS; 882 image->texture->screen->resource_get_handle(image->texture->screen, 883 image->texture, &whandle); 884 *value = whandle.handle; 885 return GL_TRUE; 886 case __DRI_IMAGE_ATTRIB_NAME: 887 whandle.type = DRM_API_HANDLE_TYPE_SHARED; 888 image->texture->screen->resource_get_handle(image->texture->screen, 889 image->texture, &whandle); 890 *value = whandle.handle; 891 return GL_TRUE; 892 case __DRI_IMAGE_ATTRIB_FD: 893 whandle.type= DRM_API_HANDLE_TYPE_FD; 894 image->texture->screen->resource_get_handle(image->texture->screen, 895 image->texture, &whandle); 896 *value = whandle.handle; 897 return GL_TRUE; 898 case __DRI_IMAGE_ATTRIB_FORMAT: 899 *value = image->dri_format; 900 return GL_TRUE; 901 case __DRI_IMAGE_ATTRIB_WIDTH: 902 *value = image->texture->width0; 903 return GL_TRUE; 904 case __DRI_IMAGE_ATTRIB_HEIGHT: 905 *value = image->texture->height0; 906 return GL_TRUE; 907 case __DRI_IMAGE_ATTRIB_COMPONENTS: 908 if (image->dri_components == 0) 909 return GL_FALSE; 910 *value = image->dri_components; 911 return GL_TRUE; 912 default: 913 return GL_FALSE; 914 } 915} 916 917static __DRIimage * 918dri2_dup_image(__DRIimage *image, void *loaderPrivate) 919{ 920 __DRIimage *img; 921 922 img = CALLOC_STRUCT(__DRIimageRec); 923 if (!img) 924 return NULL; 925 926 img->texture = NULL; 927 pipe_resource_reference(&img->texture, image->texture); 928 img->level = image->level; 929 img->layer = image->layer; 930 img->dri_format = image->dri_format; 931 /* This should be 0 for sub images, but dup is also used for base images. */ 932 img->dri_components = image->dri_components; 933 img->loader_private = loaderPrivate; 934 935 return img; 936} 937 938static GLboolean 939dri2_validate_usage(__DRIimage *image, unsigned int use) 940{ 941 /* 942 * Gallium drivers are bad at adding usages to the resources 943 * once opened again in another process, which is the main use 944 * case for this, so we have to lie. 945 */ 946 if (image != NULL) 947 return GL_TRUE; 948 else 949 return GL_FALSE; 950} 951 952static __DRIimage * 953dri2_from_names(__DRIscreen *screen, int width, int height, int format, 954 int *names, int num_names, int *strides, int *offsets, 955 void *loaderPrivate) 956{ 957 __DRIimage *img; 958 int stride, dri_components; 959 960 if (num_names != 1) 961 return NULL; 962 if (offsets[0] != 0) 963 return NULL; 964 965 format = convert_fourcc(format, &dri_components); 966 if (format == -1) 967 return NULL; 968 969 /* Strides are in bytes not pixels. */ 970 stride = strides[0] /4; 971 972 img = dri2_create_image_from_name(screen, width, height, format, 973 names[0], stride, loaderPrivate); 974 if (img == NULL) 975 return NULL; 976 977 img->dri_components = dri_components; 978 return img; 979} 980 981static __DRIimage * 982dri2_from_planar(__DRIimage *image, int plane, void *loaderPrivate) 983{ 984 __DRIimage *img; 985 986 if (plane != 0) 987 return NULL; 988 989 if (image->dri_components == 0) 990 return NULL; 991 992 img = dri2_dup_image(image, loaderPrivate); 993 if (img == NULL) 994 return NULL; 995 996 /* set this to 0 for sub images. */ 997 img->dri_components = 0; 998 return img; 999} 1000 1001static __DRIimage * 1002dri2_create_from_texture(__DRIcontext *context, int target, unsigned texture, 1003 int depth, int level, unsigned *error, 1004 void *loaderPrivate) 1005{ 1006 __DRIimage *img; 1007 struct gl_context *ctx = ((struct st_context *)dri_context(context)->st)->ctx; 1008 struct gl_texture_object *obj; 1009 struct pipe_resource *tex; 1010 GLuint face = 0; 1011 1012 obj = _mesa_lookup_texture(ctx, texture); 1013 if (!obj || obj->Target != target) { 1014 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 1015 return NULL; 1016 } 1017 1018 tex = st_get_texobj_resource(obj); 1019 if (!tex) { 1020 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 1021 return NULL; 1022 } 1023 1024 if (target == GL_TEXTURE_CUBE_MAP) 1025 face = depth; 1026 1027 _mesa_test_texobj_completeness(ctx, obj); 1028 if (!obj->_BaseComplete || (level > 0 && !obj->_MipmapComplete)) { 1029 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 1030 return NULL; 1031 } 1032 1033 if (level < obj->BaseLevel || level > obj->_MaxLevel) { 1034 *error = __DRI_IMAGE_ERROR_BAD_MATCH; 1035 return NULL; 1036 } 1037 1038 if (target == GL_TEXTURE_3D && obj->Image[face][level]->Depth < depth) { 1039 *error = __DRI_IMAGE_ERROR_BAD_MATCH; 1040 return NULL; 1041 } 1042 1043 img = CALLOC_STRUCT(__DRIimageRec); 1044 if (!img) { 1045 *error = __DRI_IMAGE_ERROR_BAD_ALLOC; 1046 return NULL; 1047 } 1048 1049 img->level = level; 1050 img->layer = depth; 1051 img->dri_format = driGLFormatToImageFormat(obj->Image[face][level]->TexFormat); 1052 1053 img->loader_private = loaderPrivate; 1054 1055 if (img->dri_format == __DRI_IMAGE_FORMAT_NONE) { 1056 *error = __DRI_IMAGE_ERROR_BAD_PARAMETER; 1057 free(img); 1058 return NULL; 1059 } 1060 1061 pipe_resource_reference(&img->texture, tex); 1062 1063 *error = __DRI_IMAGE_ERROR_SUCCESS; 1064 return img; 1065} 1066 1067static __DRIimage * 1068dri2_from_fds(__DRIscreen *screen, int width, int height, int fourcc, 1069 int *fds, int num_fds, int *strides, int *offsets, 1070 void *loaderPrivate) 1071{ 1072 __DRIimage *img; 1073 int format, stride, dri_components; 1074 1075 if (num_fds != 1) 1076 return NULL; 1077 if (offsets[0] != 0) 1078 return NULL; 1079 1080 format = convert_fourcc(fourcc, &dri_components); 1081 if (format == -1) 1082 return NULL; 1083 1084 /* Strides are in bytes not pixels. */ 1085 stride = strides[0] /4; 1086 1087 img = dri2_create_image_from_fd(screen, width, height, format, 1088 fds[0], stride, loaderPrivate); 1089 if (img == NULL) 1090 return NULL; 1091 1092 img->dri_components = dri_components; 1093 return img; 1094} 1095 1096static __DRIimage * 1097dri2_from_dma_bufs(__DRIscreen *screen, 1098 int width, int height, int fourcc, 1099 int *fds, int num_fds, 1100 int *strides, int *offsets, 1101 enum __DRIYUVColorSpace yuv_color_space, 1102 enum __DRISampleRange sample_range, 1103 enum __DRIChromaSiting horizontal_siting, 1104 enum __DRIChromaSiting vertical_siting, 1105 unsigned *error, 1106 void *loaderPrivate) 1107{ 1108 __DRIimage *img; 1109 int format, stride, dri_components; 1110 1111 if (num_fds != 1 || offsets[0] != 0) { 1112 *error = __DRI_IMAGE_ERROR_BAD_MATCH; 1113 return NULL; 1114 } 1115 1116 format = convert_fourcc(fourcc, &dri_components); 1117 if (format == -1) { 1118 *error = __DRI_IMAGE_ERROR_BAD_MATCH; 1119 return NULL; 1120 } 1121 1122 /* Strides are in bytes not pixels. */ 1123 stride = strides[0] /4; 1124 1125 img = dri2_create_image_from_fd(screen, width, height, format, 1126 fds[0], stride, loaderPrivate); 1127 if (img == NULL) { 1128 *error = __DRI_IMAGE_ERROR_BAD_ALLOC; 1129 return NULL; 1130 } 1131 1132 img->yuv_color_space = yuv_color_space; 1133 img->sample_range = sample_range; 1134 img->horizontal_siting = horizontal_siting; 1135 img->vertical_siting = vertical_siting; 1136 img->dri_components = dri_components; 1137 1138 *error = __DRI_IMAGE_ERROR_SUCCESS; 1139 return img; 1140} 1141 1142static void 1143dri2_blit_image(__DRIcontext *context, __DRIimage *dst, __DRIimage *src, 1144 int dstx0, int dsty0, int dstwidth, int dstheight, 1145 int srcx0, int srcy0, int srcwidth, int srcheight, 1146 int flush_flag) 1147{ 1148 struct dri_context *ctx = dri_context(context); 1149 struct pipe_context *pipe = ctx->st->pipe; 1150 struct pipe_screen *screen; 1151 struct pipe_fence_handle *fence; 1152 struct pipe_blit_info blit; 1153 1154 if (!dst || !src) 1155 return; 1156 1157 memset(&blit, 0, sizeof(blit)); 1158 blit.dst.resource = dst->texture; 1159 blit.dst.box.x = dstx0; 1160 blit.dst.box.y = dsty0; 1161 blit.dst.box.width = dstwidth; 1162 blit.dst.box.height = dstheight; 1163 blit.dst.box.depth = 1; 1164 blit.dst.format = dst->texture->format; 1165 blit.src.resource = src->texture; 1166 blit.src.box.x = srcx0; 1167 blit.src.box.y = srcy0; 1168 blit.src.box.width = srcwidth; 1169 blit.src.box.height = srcheight; 1170 blit.src.box.depth = 1; 1171 blit.src.format = src->texture->format; 1172 blit.mask = PIPE_MASK_RGBA; 1173 blit.filter = PIPE_TEX_FILTER_NEAREST; 1174 1175 pipe->blit(pipe, &blit); 1176 1177 if (flush_flag == __BLIT_FLAG_FLUSH) { 1178 pipe->flush_resource(pipe, dst->texture); 1179 ctx->st->flush(ctx->st, 0, NULL); 1180 } else if (flush_flag == __BLIT_FLAG_FINISH) { 1181 screen = dri_screen(ctx->sPriv)->base.screen; 1182 pipe->flush_resource(pipe, dst->texture); 1183 ctx->st->flush(ctx->st, 0, &fence); 1184 (void) screen->fence_finish(screen, fence, PIPE_TIMEOUT_INFINITE); 1185 screen->fence_reference(screen, &fence, NULL); 1186 } 1187} 1188 1189static void 1190dri2_destroy_image(__DRIimage *img) 1191{ 1192 pipe_resource_reference(&img->texture, NULL); 1193 FREE(img); 1194} 1195 1196static int 1197dri2_get_capabilities(__DRIscreen *_screen) 1198{ 1199 struct dri_screen *screen = dri_screen(_screen); 1200 1201 return (screen->can_share_buffer ? __DRI_IMAGE_CAP_GLOBAL_NAMES : 0); 1202} 1203 1204/* The extension is modified during runtime if DRI_PRIME is detected */ 1205static __DRIimageExtension dri2ImageExtension = { 1206 .base = { __DRI_IMAGE, 10 }, 1207 1208 .createImageFromName = dri2_create_image_from_name, 1209 .createImageFromRenderbuffer = dri2_create_image_from_renderbuffer, 1210 .destroyImage = dri2_destroy_image, 1211 .createImage = dri2_create_image, 1212 .queryImage = dri2_query_image, 1213 .dupImage = dri2_dup_image, 1214 .validateUsage = dri2_validate_usage, 1215 .createImageFromNames = dri2_from_names, 1216 .fromPlanar = dri2_from_planar, 1217 .createImageFromTexture = dri2_create_from_texture, 1218 .createImageFromFds = NULL, 1219 .createImageFromDmaBufs = NULL, 1220 .blitImage = dri2_blit_image, 1221 .getCapabilities = dri2_get_capabilities, 1222}; 1223 1224/* 1225 * Backend function init_screen. 1226 */ 1227 1228static const __DRIextension *dri_screen_extensions[] = { 1229 &driTexBufferExtension.base, 1230 &dri2FlushExtension.base, 1231 &dri2ImageExtension.base, 1232 &dri2RendererQueryExtension.base, 1233 &dri2ConfigQueryExtension.base, 1234 &dri2ThrottleExtension.base, 1235 NULL 1236}; 1237 1238/** 1239 * This is the driver specific part of the createNewScreen entry point. 1240 * 1241 * Returns the struct gl_config supported by this driver. 1242 */ 1243static const __DRIconfig ** 1244dri2_init_screen(__DRIscreen * sPriv) 1245{ 1246 const __DRIconfig **configs; 1247 struct dri_screen *screen; 1248 struct pipe_screen *pscreen = NULL; 1249 const struct drm_conf_ret *throttle_ret = NULL; 1250 const struct drm_conf_ret *dmabuf_ret = NULL; 1251 1252 screen = CALLOC_STRUCT(dri_screen); 1253 if (!screen) 1254 return NULL; 1255 1256 screen->sPriv = sPriv; 1257 screen->fd = sPriv->fd; 1258 1259 sPriv->driverPrivate = (void *)screen; 1260 1261#if GALLIUM_STATIC_TARGETS 1262 pscreen = dd_create_screen(screen->fd); 1263 1264 throttle_ret = dd_configuration(DRM_CONF_THROTTLE); 1265 dmabuf_ret = dd_configuration(DRM_CONF_SHARE_FD); 1266#else 1267 if (pipe_loader_drm_probe_fd(&screen->dev, screen->fd, true)) { 1268 pscreen = pipe_loader_create_screen(screen->dev, PIPE_SEARCH_DIR); 1269 1270 throttle_ret = pipe_loader_configuration(screen->dev, DRM_CONF_THROTTLE); 1271 dmabuf_ret = pipe_loader_configuration(screen->dev, DRM_CONF_SHARE_FD); 1272 } 1273#endif // GALLIUM_STATIC_TARGETS 1274 1275 if (throttle_ret && throttle_ret->val.val_int != -1) { 1276 screen->throttling_enabled = TRUE; 1277 screen->default_throttle_frames = throttle_ret->val.val_int; 1278 } 1279 1280 if (dmabuf_ret && dmabuf_ret->val.val_bool) { 1281 uint64_t cap; 1282 1283 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && 1284 (cap & DRM_PRIME_CAP_IMPORT)) { 1285 dri2ImageExtension.createImageFromFds = dri2_from_fds; 1286 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; 1287 } 1288 } 1289 1290 sPriv->extensions = dri_screen_extensions; 1291 1292 /* dri_init_screen_helper checks pscreen for us */ 1293 1294#if GALLIUM_STATIC_TARGETS 1295 configs = dri_init_screen_helper(screen, pscreen, dd_driver_name()); 1296#else 1297 configs = dri_init_screen_helper(screen, pscreen, screen->dev->driver_name); 1298#endif // GALLIUM_STATIC_TARGETS 1299 if (!configs) 1300 goto fail; 1301 1302 screen->can_share_buffer = true; 1303 screen->auto_fake_front = dri_with_format(sPriv); 1304 screen->broken_invalidate = !sPriv->dri2.useInvalidate; 1305 screen->lookup_egl_image = dri2_lookup_egl_image; 1306 1307 return configs; 1308fail: 1309 dri_destroy_screen_helper(screen); 1310#if !GALLIUM_STATIC_TARGETS 1311 if (screen->dev) 1312 pipe_loader_release(&screen->dev, 1); 1313#endif // !GALLIUM_STATIC_TARGETS 1314 FREE(screen); 1315 return NULL; 1316} 1317 1318/** 1319 * This is the driver specific part of the createNewScreen entry point. 1320 * 1321 * Returns the struct gl_config supported by this driver. 1322 */ 1323static const __DRIconfig ** 1324dri_kms_init_screen(__DRIscreen * sPriv) 1325{ 1326#if GALLIUM_STATIC_TARGETS 1327#if defined(GALLIUM_SOFTPIPE) 1328 const __DRIconfig **configs; 1329 struct dri_screen *screen; 1330 struct pipe_screen *pscreen = NULL; 1331 uint64_t cap; 1332 1333 screen = CALLOC_STRUCT(dri_screen); 1334 if (!screen) 1335 return NULL; 1336 1337 screen->sPriv = sPriv; 1338 screen->fd = sPriv->fd; 1339 1340 sPriv->driverPrivate = (void *)screen; 1341 1342 pscreen = kms_swrast_create_screen(screen->fd); 1343 1344 if (drmGetCap(sPriv->fd, DRM_CAP_PRIME, &cap) == 0 && 1345 (cap & DRM_PRIME_CAP_IMPORT)) { 1346 dri2ImageExtension.createImageFromFds = dri2_from_fds; 1347 dri2ImageExtension.createImageFromDmaBufs = dri2_from_dma_bufs; 1348 } 1349 1350 sPriv->extensions = dri_screen_extensions; 1351 1352 /* dri_init_screen_helper checks pscreen for us */ 1353 configs = dri_init_screen_helper(screen, pscreen, "swrast"); 1354 if (!configs) 1355 goto fail; 1356 1357 screen->can_share_buffer = false; 1358 screen->auto_fake_front = dri_with_format(sPriv); 1359 screen->broken_invalidate = !sPriv->dri2.useInvalidate; 1360 screen->lookup_egl_image = dri2_lookup_egl_image; 1361 1362 return configs; 1363fail: 1364 dri_destroy_screen_helper(screen); 1365 FREE(screen); 1366#endif // GALLIUM_SOFTPIPE 1367#endif // GALLIUM_STATIC_TARGETS 1368 return NULL; 1369} 1370 1371static boolean 1372dri2_create_buffer(__DRIscreen * sPriv, 1373 __DRIdrawable * dPriv, 1374 const struct gl_config * visual, boolean isPixmap) 1375{ 1376 struct dri_drawable *drawable = NULL; 1377 1378 if (!dri_create_buffer(sPriv, dPriv, visual, isPixmap)) 1379 return FALSE; 1380 1381 drawable = dPriv->driverPrivate; 1382 1383 drawable->allocate_textures = dri2_allocate_textures; 1384 drawable->flush_frontbuffer = dri2_flush_frontbuffer; 1385 drawable->update_tex_buffer = dri2_update_tex_buffer; 1386 1387 return TRUE; 1388} 1389 1390/** 1391 * DRI driver virtual function table. 1392 * 1393 * DRI versions differ in their implementation of init_screen and swap_buffers. 1394 */ 1395const struct __DriverAPIRec galliumdrm_driver_api = { 1396 .InitScreen = dri2_init_screen, 1397 .DestroyScreen = dri_destroy_screen, 1398 .CreateContext = dri_create_context, 1399 .DestroyContext = dri_destroy_context, 1400 .CreateBuffer = dri2_create_buffer, 1401 .DestroyBuffer = dri_destroy_buffer, 1402 .MakeCurrent = dri_make_current, 1403 .UnbindContext = dri_unbind_context, 1404 1405 .AllocateBuffer = dri2_allocate_buffer, 1406 .ReleaseBuffer = dri2_release_buffer, 1407}; 1408 1409/** 1410 * DRI driver virtual function table. 1411 * 1412 * KMS/DRM version of the DriverAPI above sporting a different InitScreen 1413 * hook. The latter is used to explicitly initialise the kms_swrast driver 1414 * rather than selecting the approapriate driver as suggested by the loader. 1415 */ 1416const struct __DriverAPIRec dri_kms_driver_api = { 1417 .InitScreen = dri_kms_init_screen, 1418 .DestroyScreen = dri_destroy_screen, 1419 .CreateContext = dri_create_context, 1420 .DestroyContext = dri_destroy_context, 1421 .CreateBuffer = dri2_create_buffer, 1422 .DestroyBuffer = dri_destroy_buffer, 1423 .MakeCurrent = dri_make_current, 1424 .UnbindContext = dri_unbind_context, 1425 1426 .AllocateBuffer = dri2_allocate_buffer, 1427 .ReleaseBuffer = dri2_release_buffer, 1428}; 1429 1430/* This is the table of extensions that the loader will dlsym() for. */ 1431const __DRIextension *galliumdrm_driver_extensions[] = { 1432 &driCoreExtension.base, 1433 &driImageDriverExtension.base, 1434 &driDRI2Extension.base, 1435 &gallium_config_options.base, 1436 NULL 1437}; 1438 1439/* vim: set sw=3 ts=8 sts=3 expandtab: */ 1440