1/* 2 * Copyright © 2008,2011 Intel Corporation 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a 5 * copy of this software and associated documentation files (the "Software"), 6 * to deal in the Software without restriction, including without limitation 7 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 8 * and/or sell copies of the Software, and to permit persons to whom the 9 * Software is furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice (including the next 12 * paragraph) shall be included in all copies or substantial portions of the 13 * Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 20 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS 21 * IN THE SOFTWARE. 22 * 23 * Authors: 24 * Eric Anholt <eric@anholt.net> 25 * Zhigang Gong <zhigang.gong@linux.intel.com> 26 * Chad Versace <chad.versace@linux.intel.com> 27 */ 28 29/** @file glamor.c 30 * This file covers the initialization and teardown of glamor, and has various 31 * functions not responsible for performing rendering. 32 */ 33 34#include <stdlib.h> 35#include <unistd.h> 36 37#include "glamor_priv.h" 38#include "mipict.h" 39 40DevPrivateKeyRec glamor_screen_private_key; 41DevPrivateKeyRec glamor_pixmap_private_key; 42DevPrivateKeyRec glamor_gc_private_key; 43 44glamor_screen_private * 45glamor_get_screen_private(ScreenPtr screen) 46{ 47 return (glamor_screen_private *) 48 dixLookupPrivate(&screen->devPrivates, &glamor_screen_private_key); 49} 50 51void 52glamor_set_screen_private(ScreenPtr screen, glamor_screen_private *priv) 53{ 54 dixSetPrivate(&screen->devPrivates, &glamor_screen_private_key, priv); 55} 56 57/** 58 * glamor_get_drawable_pixmap() returns a backing pixmap for a given drawable. 59 * 60 * @param drawable the drawable being requested. 61 * 62 * This function returns the backing pixmap for a drawable, whether it is a 63 * redirected window, unredirected window, or already a pixmap. Note that 64 * coordinate translation is needed when drawing to the backing pixmap of a 65 * redirected window, and the translation coordinates are provided by calling 66 * exaGetOffscreenPixmap() on the drawable. 67 */ 68PixmapPtr 69glamor_get_drawable_pixmap(DrawablePtr drawable) 70{ 71 if (drawable->type == DRAWABLE_WINDOW) 72 return drawable->pScreen->GetWindowPixmap((WindowPtr) drawable); 73 else 74 return (PixmapPtr) drawable; 75} 76 77static void 78glamor_init_pixmap_private_small(PixmapPtr pixmap, glamor_pixmap_private *pixmap_priv) 79{ 80 pixmap_priv->box.x1 = 0; 81 pixmap_priv->box.x2 = pixmap->drawable.width; 82 pixmap_priv->box.y1 = 0; 83 pixmap_priv->box.y2 = pixmap->drawable.height; 84 pixmap_priv->block_w = pixmap->drawable.width; 85 pixmap_priv->block_h = pixmap->drawable.height; 86 pixmap_priv->block_hcnt = 1; 87 pixmap_priv->block_wcnt = 1; 88 pixmap_priv->box_array = &pixmap_priv->box; 89 pixmap_priv->fbo_array = &pixmap_priv->fbo; 90} 91 92_X_EXPORT void 93glamor_set_pixmap_type(PixmapPtr pixmap, glamor_pixmap_type_t type) 94{ 95 glamor_pixmap_private *pixmap_priv; 96 97 pixmap_priv = glamor_get_pixmap_private(pixmap); 98 pixmap_priv->type = type; 99 glamor_init_pixmap_private_small(pixmap, pixmap_priv); 100} 101 102_X_EXPORT Bool 103glamor_set_pixmap_texture(PixmapPtr pixmap, unsigned int tex) 104{ 105 ScreenPtr screen = pixmap->drawable.pScreen; 106 glamor_pixmap_private *pixmap_priv; 107 glamor_screen_private *glamor_priv; 108 glamor_pixmap_fbo *fbo; 109 110 glamor_priv = glamor_get_screen_private(screen); 111 pixmap_priv = glamor_get_pixmap_private(pixmap); 112 113 if (pixmap_priv->fbo) { 114 fbo = glamor_pixmap_detach_fbo(pixmap_priv); 115 glamor_destroy_fbo(glamor_priv, fbo); 116 } 117 118 fbo = glamor_create_fbo_from_tex(glamor_priv, pixmap, 119 pixmap->drawable.width, 120 pixmap->drawable.height, tex, 0); 121 122 if (fbo == NULL) { 123 ErrorF("XXX fail to create fbo.\n"); 124 return FALSE; 125 } 126 127 glamor_pixmap_attach_fbo(pixmap, fbo); 128 129 return TRUE; 130} 131 132_X_EXPORT void 133glamor_clear_pixmap(PixmapPtr pixmap) 134{ 135 ScreenPtr screen = pixmap->drawable.pScreen; 136 glamor_screen_private *glamor_priv; 137 glamor_pixmap_private *pixmap_priv; 138 const struct glamor_format *pixmap_format; 139 140 glamor_priv = glamor_get_screen_private(screen); 141 pixmap_priv = glamor_get_pixmap_private(pixmap); 142 pixmap_format = glamor_format_for_pixmap(pixmap); 143 144 assert(pixmap_priv->fbo != NULL); 145 146 glamor_pixmap_clear_fbo(glamor_priv, pixmap_priv->fbo, pixmap_format); 147} 148 149uint32_t 150glamor_get_pixmap_texture(PixmapPtr pixmap) 151{ 152 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 153 154 if (!pixmap_priv) 155 return 0; 156 157 if (!pixmap_priv->fbo) 158 return 0; 159 160 if (pixmap_priv->type != GLAMOR_TEXTURE_ONLY) 161 return 0; 162 163 return pixmap_priv->fbo->tex; 164} 165 166void 167glamor_bind_texture(glamor_screen_private *glamor_priv, GLenum texture, 168 glamor_pixmap_fbo *fbo, Bool destination_red) 169{ 170 glActiveTexture(texture); 171 glBindTexture(GL_TEXTURE_2D, fbo->tex); 172 173 /* If we're pulling data from a GL_RED texture, then whether we 174 * want to make it an A,0,0,0 result or a 0,0,0,R result depends 175 * on whether the destination is also a GL_RED texture. 176 * 177 * For GL_RED destinations, we need to leave the bits in the R 178 * channel. For all other destinations, we need to clear out the R 179 * channel so that it returns zero for R, G and B. 180 * 181 * Note that we're leaving the SWIZZLE_A value alone; for GL_RED 182 * destinations, that means we'll actually be returning R,0,0,R, 183 * but it doesn't matter as the bits in the alpha channel aren't 184 * going anywhere. 185 */ 186 187 /* Is the operand a GL_RED fbo? 188 */ 189 190 if (fbo->is_red) { 191 /* If destination is also GL_RED, then preserve the bits in 192 * the R channel */ 193 194 if (destination_red) 195 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_RED); 196 else 197 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_SWIZZLE_R, GL_ZERO); 198 } 199} 200 201PixmapPtr 202glamor_create_pixmap(ScreenPtr screen, int w, int h, int depth, 203 unsigned int usage) 204{ 205 PixmapPtr pixmap; 206 glamor_pixmap_private *pixmap_priv; 207 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 208 glamor_pixmap_fbo *fbo = NULL; 209 int pitch; 210 211 if (w > 32767 || h > 32767) 212 return NullPixmap; 213 214 if ((usage == GLAMOR_CREATE_PIXMAP_CPU 215 || (usage == CREATE_PIXMAP_USAGE_GLYPH_PICTURE && 216 w <= glamor_priv->glyph_max_dim && 217 h <= glamor_priv->glyph_max_dim) 218 || (w == 0 && h == 0) 219 || !glamor_priv->formats[depth].rendering_supported)) 220 return fbCreatePixmap(screen, w, h, depth, usage); 221 else 222 pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 223 224 pixmap_priv = glamor_get_pixmap_private(pixmap); 225 226 pixmap_priv->is_cbcr = (usage == GLAMOR_CREATE_FORMAT_CBCR); 227 228 pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; 229 screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); 230 231 pixmap_priv->type = GLAMOR_TEXTURE_ONLY; 232 233 if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) { 234 glamor_init_pixmap_private_small(pixmap, pixmap_priv); 235 return pixmap; 236 } 237 else if (usage == GLAMOR_CREATE_NO_LARGE || 238 glamor_check_fbo_size(glamor_priv, w, h)) 239 { 240 glamor_init_pixmap_private_small(pixmap, pixmap_priv); 241 fbo = glamor_create_fbo(glamor_priv, pixmap, w, h, usage); 242 } else { 243 int tile_size = glamor_priv->max_fbo_size; 244 DEBUGF("Create LARGE pixmap %p width %d height %d, tile size %d\n", 245 pixmap, w, h, tile_size); 246 fbo = glamor_create_fbo_array(glamor_priv, pixmap, usage, 247 tile_size, tile_size, pixmap_priv); 248 } 249 250 if (fbo == NULL) { 251 fbDestroyPixmap(pixmap); 252 return fbCreatePixmap(screen, w, h, depth, usage); 253 } 254 255 glamor_pixmap_attach_fbo(pixmap, fbo); 256 257 return pixmap; 258} 259 260Bool 261glamor_destroy_pixmap(PixmapPtr pixmap) 262{ 263 if (pixmap->refcnt == 1) { 264 glamor_pixmap_destroy_fbo(pixmap); 265 } 266 267 return fbDestroyPixmap(pixmap); 268} 269 270void 271glamor_block_handler(ScreenPtr screen) 272{ 273 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 274 275 glamor_make_current(glamor_priv); 276 glFlush(); 277} 278 279static void 280_glamor_block_handler(ScreenPtr screen, void *timeout) 281{ 282 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 283 284 glamor_make_current(glamor_priv); 285 glFlush(); 286 287 screen->BlockHandler = glamor_priv->saved_procs.block_handler; 288 screen->BlockHandler(screen, timeout); 289 glamor_priv->saved_procs.block_handler = screen->BlockHandler; 290 screen->BlockHandler = _glamor_block_handler; 291} 292 293static void 294glamor_set_debug_level(int *debug_level) 295{ 296 char *debug_level_string; 297 298 debug_level_string = getenv("GLAMOR_DEBUG"); 299 if (debug_level_string 300 && sscanf(debug_level_string, "%d", debug_level) == 1) 301 return; 302 *debug_level = 0; 303} 304 305int glamor_debug_level; 306 307void 308glamor_gldrawarrays_quads_using_indices(glamor_screen_private *glamor_priv, 309 unsigned count) 310{ 311 unsigned i; 312 313 /* For a single quad, don't bother with an index buffer. */ 314 if (count == 1) 315 goto fallback; 316 317 if (glamor_priv->ib_size < count) { 318 /* Basic GLES2 doesn't have any way to map buffer objects for 319 * writing, but it's long past time for drivers to have 320 * MapBufferRange. 321 */ 322 if (!glamor_priv->has_map_buffer_range) 323 goto fallback; 324 325 /* Lazy create the buffer name, and only bind it once since 326 * none of the glamor code binds it to anything else. 327 */ 328 if (!glamor_priv->ib) { 329 glGenBuffers(1, &glamor_priv->ib); 330 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ib); 331 } 332 333 /* For now, only support GL_UNSIGNED_SHORTs. */ 334 if (count > ((1 << 16) - 1) / 4) { 335 goto fallback; 336 } else { 337 uint16_t *data; 338 size_t size = count * 6 * sizeof(GLushort); 339 340 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW); 341 data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 342 0, size, 343 GL_MAP_WRITE_BIT | 344 GL_MAP_INVALIDATE_BUFFER_BIT); 345 for (i = 0; i < count; i++) { 346 data[i * 6 + 0] = i * 4 + 0; 347 data[i * 6 + 1] = i * 4 + 1; 348 data[i * 6 + 2] = i * 4 + 2; 349 data[i * 6 + 3] = i * 4 + 0; 350 data[i * 6 + 4] = i * 4 + 2; 351 data[i * 6 + 5] = i * 4 + 3; 352 } 353 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); 354 355 glamor_priv->ib_size = count; 356 glamor_priv->ib_type = GL_UNSIGNED_SHORT; 357 } 358 } 359 360 glDrawElements(GL_TRIANGLES, count * 6, glamor_priv->ib_type, NULL); 361 return; 362 363fallback: 364 for (i = 0; i < count; i++) 365 glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); 366} 367 368 369static Bool 370glamor_check_instruction_count(int gl_version) 371{ 372 GLint max_native_alu_instructions; 373 374 /* Avoid using glamor if the reported instructions limit is too low, 375 * as this would cause glamor to fallback on sw due to large shaders 376 * which ends up being unbearably slow. 377 */ 378 if (gl_version < 30) { 379 if (!epoxy_has_gl_extension("GL_ARB_fragment_program")) { 380 ErrorF("GL_ARB_fragment_program required\n"); 381 return FALSE; 382 } 383 384 glGetProgramivARB(GL_FRAGMENT_PROGRAM_ARB, 385 GL_MAX_PROGRAM_NATIVE_ALU_INSTRUCTIONS_ARB, 386 &max_native_alu_instructions); 387 if (max_native_alu_instructions < GLAMOR_MIN_ALU_INSTRUCTIONS) { 388 LogMessage(X_WARNING, 389 "glamor requires at least %d instructions (%d reported)\n", 390 GLAMOR_MIN_ALU_INSTRUCTIONS, max_native_alu_instructions); 391 return FALSE; 392 } 393 } 394 395 return TRUE; 396} 397 398static void GLAPIENTRY 399glamor_debug_output_callback(GLenum source, 400 GLenum type, 401 GLuint id, 402 GLenum severity, 403 GLsizei length, 404 const GLchar *message, 405 const void *userParam) 406{ 407 ScreenPtr screen = (void *)userParam; 408 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 409 410 if (glamor_priv->suppress_gl_out_of_memory_logging && 411 source == GL_DEBUG_SOURCE_API && type == GL_DEBUG_TYPE_ERROR) { 412 return; 413 } 414 415 LogMessageVerb(X_ERROR, 0, "glamor%d: GL error: %*s\n", 416 screen->myNum, length, message); 417 xorg_backtrace(); 418} 419 420/** 421 * Configures GL_ARB_debug_output to give us immediate callbacks when 422 * GL errors occur, so that we can log them. 423 */ 424static void 425glamor_setup_debug_output(ScreenPtr screen) 426{ 427 if (!epoxy_has_gl_extension("GL_KHR_debug") && 428 !epoxy_has_gl_extension("GL_ARB_debug_output")) 429 return; 430 431 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 432 /* Disable debugging messages other than GL API errors */ 433 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, 434 GL_FALSE); 435 glDebugMessageControl(GL_DEBUG_SOURCE_API, 436 GL_DEBUG_TYPE_ERROR, 437 GL_DONT_CARE, 438 0, NULL, GL_TRUE); 439 glDebugMessageCallback(glamor_debug_output_callback, 440 screen); 441 442 /* If KHR_debug is present, all debug output is disabled by 443 * default on non-debug contexts. 444 */ 445 if (epoxy_has_gl_extension("GL_KHR_debug")) 446 glEnable(GL_DEBUG_OUTPUT); 447} 448 449const struct glamor_format * 450glamor_format_for_pixmap(PixmapPtr pixmap) 451{ 452 ScreenPtr pScreen = pixmap->drawable.pScreen; 453 glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen); 454 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 455 456 if (pixmap_priv->is_cbcr) 457 return &glamor_priv->cbcr_format; 458 else 459 return &glamor_priv->formats[pixmap->drawable.depth]; 460} 461 462static void 463glamor_add_format(ScreenPtr screen, int depth, CARD32 render_format, 464 GLenum internalformat, GLenum format, GLenum type, 465 Bool rendering_supported) 466{ 467 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 468 struct glamor_format *f = &glamor_priv->formats[depth]; 469 470 /* If we're trying to run on GLES, make sure that we get the read 471 * formats that we're expecting, since glamor_transfer relies on 472 * them matching to get data back out. To avoid this limitation, we 473 * would need to have a more general glReadPixels() path in 474 * glamor_transfer that re-encoded the bits to the pixel format that 475 * we intended after. 476 * 477 * Note that we can't just create a pixmap because we're in 478 * screeninit. 479 */ 480 if (rendering_supported && glamor_priv->is_gles) { 481 unsigned fbo, tex; 482 int read_format, read_type; 483 GLenum status; 484 485 glGenTextures(1, &tex); 486 glBindTexture(GL_TEXTURE_2D, tex); 487 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 488 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 489 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, 490 format, type, NULL); 491 492 glGenFramebuffers(1, &fbo); 493 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 494 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 495 GL_TEXTURE_2D, tex, 0); 496 status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 497 if (status != GL_FRAMEBUFFER_COMPLETE) { 498 ErrorF("glamor: Test fbo for depth %d incomplete. " 499 "Falling back to software.\n", depth); 500 glDeleteTextures(1, &tex); 501 glDeleteFramebuffers(1, &fbo); 502 return; 503 } 504 505 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &read_format); 506 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &read_type); 507 508 glDeleteTextures(1, &tex); 509 glDeleteFramebuffers(1, &fbo); 510 511 if (format != read_format || type != read_type) { 512 ErrorF("glamor: Implementation returned 0x%x/0x%x read format/type " 513 "for depth %d, expected 0x%x/0x%x. " 514 "Falling back to software.\n", 515 read_format, read_type, depth, format, type); 516 return; 517 } 518 } 519 520 f->depth = depth; 521 f->render_format = render_format; 522 f->internalformat = internalformat; 523 f->format = format; 524 f->type = type; 525 f->rendering_supported = rendering_supported; 526} 527 528/* Set up the GL format/types that glamor will use for the various depths 529 * 530 * X11's pixel data doesn't have channels, but to store our data in GL 531 * we have to pick some sort of format to move X11 pixel data in and 532 * out with in glamor_transfer.c. For X11 core operations, other than 533 * GL logic ops (non-GXcopy GC ops) what the driver chooses internally 534 * doesn't matter as long as it doesn't drop any bits (we expect them 535 * to generally expand, if anything). For Render, we can expect 536 * clients to tend to render with PictFormats matching our channel 537 * layouts here since ultimately X11 pixels tend to end up on the 538 * screen. The render implementation will fall back to fb if the 539 * channels don't match. 540 * 541 * Note that these formats don't affect what glamor_egl.c or 542 * Xwayland's EGL layer choose for surfaces exposed through DRI or 543 * scanout. For now, those layers need to match what we're choosing 544 * here, or channels will end up swizzled around. Similarly, the 545 * driver's visual masks also need to match what we're doing here. 546 */ 547static void 548glamor_setup_formats(ScreenPtr screen) 549{ 550 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 551 552 /* Prefer r8 textures since they're required by GLES3 and core, 553 * only falling back to a8 if we can't do them. 554 */ 555 if (glamor_priv->is_gles || epoxy_has_gl_extension("GL_ARB_texture_rg")) { 556 glamor_add_format(screen, 1, PICT_a1, 557 GL_R8, GL_RED, GL_UNSIGNED_BYTE, FALSE); 558 glamor_add_format(screen, 8, PICT_a8, 559 GL_R8, GL_RED, GL_UNSIGNED_BYTE, TRUE); 560 } else { 561 glamor_add_format(screen, 1, PICT_a1, 562 GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, FALSE); 563 glamor_add_format(screen, 8, PICT_a8, 564 GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, TRUE); 565 } 566 567 if (glamor_priv->is_gles) { 568 /* For 15bpp, GLES supports format/type RGBA/5551, rather than 569 * bgra/1555_rev. GL_EXT_bgra lets the impl say the color 570 * read format/type is bgra/1555 even if we had to create it 571 * with rgba/5551, with Mesa does. That means we can't use 572 * the same format/type for TexSubImage and readpixels. 573 * 574 * Instead, just store 16 bits using the trusted 565 path, and 575 * disable render accel for now. 576 */ 577 glamor_add_format(screen, 15, PICT_x1r5g5b5, 578 GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, TRUE); 579 } else { 580 glamor_add_format(screen, 15, PICT_x1r5g5b5, 581 GL_RGBA, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, TRUE); 582 } 583 584 glamor_add_format(screen, 16, PICT_r5g6b5, 585 GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, TRUE); 586 587 if (glamor_priv->is_gles) { 588 assert(X_BYTE_ORDER == X_LITTLE_ENDIAN); 589 glamor_add_format(screen, 24, PICT_x8r8g8b8, 590 GL_BGRA, GL_BGRA, GL_UNSIGNED_BYTE, TRUE); 591 glamor_add_format(screen, 32, PICT_a8r8g8b8, 592 GL_BGRA, GL_BGRA, GL_UNSIGNED_BYTE, TRUE); 593 } else { 594 glamor_add_format(screen, 24, PICT_x8r8g8b8, 595 GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE); 596 glamor_add_format(screen, 32, PICT_a8r8g8b8, 597 GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE); 598 } 599 600 if (glamor_priv->is_gles) { 601 glamor_add_format(screen, 30, PICT_x2b10g10r10, 602 GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE); 603 } else { 604 glamor_add_format(screen, 30, PICT_x2r10g10b10, 605 GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE); 606 } 607 608 glamor_priv->cbcr_format.depth = 16; 609 glamor_priv->cbcr_format.internalformat = GL_RG8; 610 glamor_priv->cbcr_format.format = GL_RG; 611 glamor_priv->cbcr_format.type = GL_UNSIGNED_BYTE; 612 glamor_priv->cbcr_format.rendering_supported = TRUE; 613} 614 615/** Set up glamor for an already-configured GL context. */ 616Bool 617glamor_init(ScreenPtr screen, unsigned int flags) 618{ 619 glamor_screen_private *glamor_priv; 620 int gl_version; 621 int glsl_major, glsl_minor; 622 int max_viewport_size[2]; 623 const char *shading_version_string; 624 int shading_version_offset; 625 626 PictureScreenPtr ps = GetPictureScreenIfSet(screen); 627 628 if (flags & ~GLAMOR_VALID_FLAGS) { 629 ErrorF("glamor_init: Invalid flags %x\n", flags); 630 return FALSE; 631 } 632 glamor_priv = calloc(1, sizeof(*glamor_priv)); 633 if (glamor_priv == NULL) 634 return FALSE; 635 636 glamor_priv->flags = flags; 637 638 if (!dixRegisterPrivateKey(&glamor_screen_private_key, PRIVATE_SCREEN, 0)) { 639 LogMessage(X_WARNING, 640 "glamor%d: Failed to allocate screen private\n", 641 screen->myNum); 642 goto free_glamor_private; 643 } 644 645 glamor_set_screen_private(screen, glamor_priv); 646 647 if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP, 648 sizeof(struct glamor_pixmap_private))) { 649 LogMessage(X_WARNING, 650 "glamor%d: Failed to allocate pixmap private\n", 651 screen->myNum); 652 goto free_glamor_private; 653 } 654 655 if (!dixRegisterPrivateKey(&glamor_gc_private_key, PRIVATE_GC, 656 sizeof (glamor_gc_private))) { 657 LogMessage(X_WARNING, 658 "glamor%d: Failed to allocate gc private\n", 659 screen->myNum); 660 goto free_glamor_private; 661 } 662 663 glamor_priv->saved_procs.close_screen = screen->CloseScreen; 664 screen->CloseScreen = glamor_close_screen; 665 666 glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap; 667 screen->DestroyPixmap = glamor_destroy_pixmap; 668 669 /* If we are using egl screen, call egl screen init to 670 * register correct close screen function. */ 671 if (flags & GLAMOR_USE_EGL_SCREEN) { 672 glamor_egl_screen_init(screen, &glamor_priv->ctx); 673 } else { 674 if (!glamor_glx_screen_init(&glamor_priv->ctx)) 675 goto fail; 676 } 677 678 glamor_make_current(glamor_priv); 679 680 if (!epoxy_is_desktop_gl()) 681 glamor_priv->is_gles = TRUE; 682 683 gl_version = epoxy_gl_version(); 684 685 /* assume a core profile if we are GL 3.1 and don't have ARB_compatibility */ 686 glamor_priv->is_core_profile = 687 gl_version >= 31 && !epoxy_has_gl_extension("GL_ARB_compatibility"); 688 689 shading_version_string = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION); 690 691 if (!shading_version_string) { 692 LogMessage(X_WARNING, 693 "glamor%d: Failed to get GLSL version\n", 694 screen->myNum); 695 goto fail; 696 } 697 698 shading_version_offset = 0; 699 if (strncmp("OpenGL ES GLSL ES ", shading_version_string, 18) == 0) 700 shading_version_offset = 18; 701 702 if (sscanf(shading_version_string + shading_version_offset, 703 "%i.%i", 704 &glsl_major, 705 &glsl_minor) != 2) { 706 LogMessage(X_WARNING, 707 "glamor%d: Failed to parse GLSL version string %s\n", 708 screen->myNum, shading_version_string); 709 goto fail; 710 } 711 glamor_priv->glsl_version = glsl_major * 100 + glsl_minor; 712 713 if (glamor_priv->is_gles) { 714 /* Force us back to the base version of our programs on an ES 715 * context, anyway. Basically glamor only uses desktop 1.20 716 * or 1.30 currently. 1.30's new features are also present in 717 * ES 3.0, but our glamor_program.c constructions use a lot of 718 * compatibility features (to reduce the diff between 1.20 and 719 * 1.30 programs). 720 */ 721 glamor_priv->glsl_version = 120; 722 } 723 724 /* We'd like to require GL_ARB_map_buffer_range or 725 * GL_OES_map_buffer_range, since it offers more information to 726 * the driver than plain old glMapBuffer() or glBufferSubData(). 727 * It's been supported on Mesa on the desktop since 2009 and on 728 * GLES2 since October 2012. It's supported on Apple's iOS 729 * drivers for SGX535 and A7, but apparently not on most Android 730 * devices (the OES extension spec wasn't released until June 731 * 2012). 732 * 733 * 82% of 0 A.D. players (desktop GL) submitting hardware reports 734 * have support for it, with most of the ones lacking it being on 735 * Windows with Intel 4-series (G45) graphics or older. 736 */ 737 if (!glamor_priv->is_gles) { 738 if (gl_version < 21) { 739 ErrorF("Require OpenGL version 2.1 or later.\n"); 740 goto fail; 741 } 742 743 if (!glamor_priv->is_core_profile && 744 !epoxy_has_gl_extension("GL_ARB_texture_border_clamp")) { 745 ErrorF("GL_ARB_texture_border_clamp required\n"); 746 goto fail; 747 } 748 749 if (!glamor_check_instruction_count(gl_version)) 750 goto fail; 751 752 /* Glamor rendering assumes that platforms with GLSL 130+ 753 * have instanced arrays, but this is not always the case. 754 * etnaviv offers GLSL 140 with OpenGL 2.1. 755 */ 756 if (glamor_glsl_has_ints(glamor_priv) && 757 !epoxy_has_gl_extension("GL_ARB_instanced_arrays")) 758 glamor_priv->glsl_version = 120; 759 } else { 760 if (gl_version < 20) { 761 ErrorF("Require Open GLES2.0 or later.\n"); 762 goto fail; 763 } 764 765 if (!epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) { 766 ErrorF("GL_EXT_texture_format_BGRA8888 required\n"); 767 goto fail; 768 } 769 770 if (!epoxy_has_gl_extension("GL_OES_texture_border_clamp")) { 771 ErrorF("GL_OES_texture_border_clamp required\n"); 772 goto fail; 773 } 774 } 775 776 if (!epoxy_has_gl_extension("GL_ARB_vertex_array_object") && 777 !epoxy_has_gl_extension("GL_OES_vertex_array_object")) { 778 ErrorF("GL_{ARB,OES}_vertex_array_object required\n"); 779 goto fail; 780 } 781 782 if (!glamor_priv->is_gles && glamor_priv->glsl_version == 120 && 783 epoxy_has_gl_extension("GL_ARB_instanced_arrays")) 784 glamor_priv->use_gpu_shader4 = epoxy_has_gl_extension("GL_EXT_gpu_shader4"); 785 786 glamor_priv->has_rw_pbo = FALSE; 787 if (!glamor_priv->is_gles) 788 glamor_priv->has_rw_pbo = TRUE; 789 790 glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug"); 791 glamor_priv->has_pack_invert = 792 epoxy_has_gl_extension("GL_MESA_pack_invert"); 793 glamor_priv->has_fbo_blit = 794 epoxy_has_gl_extension("GL_EXT_framebuffer_blit"); 795 glamor_priv->has_map_buffer_range = 796 epoxy_has_gl_extension("GL_ARB_map_buffer_range") || 797 epoxy_has_gl_extension("GL_EXT_map_buffer_range"); 798 glamor_priv->has_buffer_storage = 799 epoxy_has_gl_extension("GL_ARB_buffer_storage"); 800 glamor_priv->has_mesa_tile_raster_order = 801 epoxy_has_gl_extension("GL_MESA_tile_raster_order"); 802 glamor_priv->has_nv_texture_barrier = 803 epoxy_has_gl_extension("GL_NV_texture_barrier"); 804 glamor_priv->has_unpack_subimage = 805 !glamor_priv->is_gles || 806 epoxy_gl_version() >= 30 || 807 epoxy_has_gl_extension("GL_EXT_unpack_subimage"); 808 glamor_priv->has_pack_subimage = 809 !glamor_priv->is_gles || 810 epoxy_gl_version() >= 30 || 811 epoxy_has_gl_extension("GL_NV_pack_subimage"); 812 glamor_priv->has_dual_blend = 813 glamor_glsl_has_ints(glamor_priv) && 814 epoxy_has_gl_extension("GL_ARB_blend_func_extended"); 815 glamor_priv->has_clear_texture = 816 epoxy_gl_version() >= 44 || 817 epoxy_has_gl_extension("GL_ARB_clear_texture"); 818 819 glamor_priv->can_copyplane = (gl_version >= 30); 820 821 glamor_setup_debug_output(screen); 822 823 glamor_priv->use_quads = !glamor_priv->is_gles && 824 !glamor_priv->is_core_profile; 825 826 /* Driver-specific hack: Avoid using GL_QUADS on VC4, where 827 * they'll be emulated more expensively than we can with our 828 * cached IB. 829 */ 830 if (strstr((char *)glGetString(GL_VENDOR), "Broadcom") && 831 (strstr((char *)glGetString(GL_RENDERER), "VC4") || 832 strstr((char *)glGetString(GL_RENDERER), "V3D"))) 833 glamor_priv->use_quads = FALSE; 834 835 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); 836 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size); 837 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size); 838 glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[0]); 839 glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[1]); 840#ifdef MAX_FBO_SIZE 841 glamor_priv->max_fbo_size = MAX_FBO_SIZE; 842#endif 843 844 glamor_priv->has_texture_swizzle = 845 (epoxy_has_gl_extension("GL_ARB_texture_swizzle") || 846 (glamor_priv->is_gles && gl_version >= 30)); 847 848 glamor_setup_formats(screen); 849 850 glamor_set_debug_level(&glamor_debug_level); 851 852 if (!glamor_font_init(screen)) 853 goto fail; 854 855 glamor_priv->saved_procs.block_handler = screen->BlockHandler; 856 screen->BlockHandler = _glamor_block_handler; 857 858 if (!glamor_composite_glyphs_init(screen)) { 859 ErrorF("Failed to initialize composite masks\n"); 860 goto fail; 861 } 862 863 glamor_priv->saved_procs.create_gc = screen->CreateGC; 864 screen->CreateGC = glamor_create_gc; 865 866 glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap; 867 screen->CreatePixmap = glamor_create_pixmap; 868 869 glamor_priv->saved_procs.get_spans = screen->GetSpans; 870 screen->GetSpans = glamor_get_spans; 871 872 glamor_priv->saved_procs.get_image = screen->GetImage; 873 screen->GetImage = glamor_get_image; 874 875 glamor_priv->saved_procs.change_window_attributes = 876 screen->ChangeWindowAttributes; 877 screen->ChangeWindowAttributes = glamor_change_window_attributes; 878 879 glamor_priv->saved_procs.copy_window = screen->CopyWindow; 880 screen->CopyWindow = glamor_copy_window; 881 882 glamor_priv->saved_procs.bitmap_to_region = screen->BitmapToRegion; 883 screen->BitmapToRegion = glamor_bitmap_to_region; 884 885 glamor_priv->saved_procs.composite = ps->Composite; 886 ps->Composite = glamor_composite; 887 888 glamor_priv->saved_procs.trapezoids = ps->Trapezoids; 889 ps->Trapezoids = glamor_trapezoids; 890 891 glamor_priv->saved_procs.triangles = ps->Triangles; 892 ps->Triangles = glamor_triangles; 893 894 glamor_priv->saved_procs.addtraps = ps->AddTraps; 895 ps->AddTraps = glamor_add_traps; 896 897 glamor_priv->saved_procs.composite_rects = ps->CompositeRects; 898 ps->CompositeRects = glamor_composite_rectangles; 899 900 glamor_priv->saved_procs.glyphs = ps->Glyphs; 901 ps->Glyphs = glamor_composite_glyphs; 902 903 glamor_init_vbo(screen); 904 glamor_init_gradient_shader(screen); 905 glamor_pixmap_init(screen); 906 glamor_sync_init(screen); 907 908 glamor_priv->screen = screen; 909 910 return TRUE; 911 912 fail: 913 /* Restore default CloseScreen and DestroyPixmap handlers */ 914 screen->CloseScreen = glamor_priv->saved_procs.close_screen; 915 screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; 916 917 free_glamor_private: 918 free(glamor_priv); 919 glamor_set_screen_private(screen, NULL); 920 return FALSE; 921} 922 923static void 924glamor_release_screen_priv(ScreenPtr screen) 925{ 926 glamor_screen_private *glamor_priv; 927 928 glamor_priv = glamor_get_screen_private(screen); 929 glamor_fini_vbo(screen); 930 glamor_pixmap_fini(screen); 931 free(glamor_priv); 932 933 glamor_set_screen_private(screen, NULL); 934} 935 936Bool 937glamor_close_screen(ScreenPtr screen) 938{ 939 glamor_screen_private *glamor_priv; 940 PixmapPtr screen_pixmap; 941 PictureScreenPtr ps = GetPictureScreenIfSet(screen); 942 943 glamor_priv = glamor_get_screen_private(screen); 944 glamor_sync_close(screen); 945 glamor_composite_glyphs_fini(screen); 946 screen->CloseScreen = glamor_priv->saved_procs.close_screen; 947 948 screen->CreateGC = glamor_priv->saved_procs.create_gc; 949 screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap; 950 screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; 951 screen->GetSpans = glamor_priv->saved_procs.get_spans; 952 screen->ChangeWindowAttributes = 953 glamor_priv->saved_procs.change_window_attributes; 954 screen->CopyWindow = glamor_priv->saved_procs.copy_window; 955 screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region; 956 screen->BlockHandler = glamor_priv->saved_procs.block_handler; 957 958 ps->Composite = glamor_priv->saved_procs.composite; 959 ps->Trapezoids = glamor_priv->saved_procs.trapezoids; 960 ps->Triangles = glamor_priv->saved_procs.triangles; 961 ps->CompositeRects = glamor_priv->saved_procs.composite_rects; 962 ps->Glyphs = glamor_priv->saved_procs.glyphs; 963 964 screen_pixmap = screen->GetScreenPixmap(screen); 965 glamor_pixmap_destroy_fbo(screen_pixmap); 966 967 glamor_release_screen_priv(screen); 968 969 return screen->CloseScreen(screen); 970} 971 972void 973glamor_fini(ScreenPtr screen) 974{ 975 /* Do nothing currently. */ 976} 977 978void 979glamor_enable_dri3(ScreenPtr screen) 980{ 981 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 982 983 glamor_priv->dri3_enabled = TRUE; 984} 985 986Bool 987glamor_supports_pixmap_import_export(ScreenPtr screen) 988{ 989 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 990 991 return glamor_priv->dri3_enabled; 992} 993 994_X_EXPORT void 995glamor_set_drawable_modifiers_func(ScreenPtr screen, 996 GetDrawableModifiersFuncPtr func) 997{ 998 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 999 1000 glamor_priv->get_drawable_modifiers = func; 1001} 1002 1003_X_EXPORT Bool 1004glamor_get_drawable_modifiers(DrawablePtr draw, uint32_t format, 1005 uint32_t *num_modifiers, uint64_t **modifiers) 1006{ 1007 struct glamor_screen_private *glamor_priv = 1008 glamor_get_screen_private(draw->pScreen); 1009 1010 if (glamor_priv->get_drawable_modifiers) { 1011 return glamor_priv->get_drawable_modifiers(draw, format, 1012 num_modifiers, modifiers); 1013 } 1014 *num_modifiers = 0; 1015 *modifiers = NULL; 1016 return TRUE; 1017} 1018 1019static int 1020_glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, 1021 uint32_t *strides, uint32_t *offsets, 1022 CARD32 *size, uint64_t *modifier) 1023{ 1024 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 1025 glamor_screen_private *glamor_priv = 1026 glamor_get_screen_private(pixmap->drawable.pScreen); 1027 1028 if (!glamor_priv->dri3_enabled) 1029 return 0; 1030 switch (pixmap_priv->type) { 1031 case GLAMOR_TEXTURE_DRM: 1032 case GLAMOR_TEXTURE_ONLY: 1033 if (!glamor_pixmap_ensure_fbo(pixmap, 0)) 1034 return 0; 1035 1036 if (modifier) { 1037 return glamor_egl_fds_from_pixmap(screen, pixmap, fds, 1038 strides, offsets, 1039 modifier); 1040 } else { 1041 CARD16 stride; 1042 1043 fds[0] = glamor_egl_fd_from_pixmap(screen, pixmap, &stride, size); 1044 strides[0] = stride; 1045 1046 return fds[0] >= 0; 1047 } 1048 default: 1049 break; 1050 } 1051 return 0; 1052} 1053 1054_X_EXPORT int 1055glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, 1056 uint32_t *strides, uint32_t *offsets, 1057 uint64_t *modifier) 1058{ 1059 return _glamor_fds_from_pixmap(screen, pixmap, fds, strides, offsets, 1060 NULL, modifier); 1061} 1062 1063_X_EXPORT int 1064glamor_fd_from_pixmap(ScreenPtr screen, 1065 PixmapPtr pixmap, CARD16 *stride, CARD32 *size) 1066{ 1067 int fd; 1068 int ret; 1069 uint32_t stride32; 1070 1071 ret = _glamor_fds_from_pixmap(screen, pixmap, &fd, &stride32, NULL, size, 1072 NULL); 1073 if (ret != 1) 1074 return -1; 1075 1076 *stride = stride32; 1077 return fd; 1078} 1079 1080_X_EXPORT int 1081glamor_shareable_fd_from_pixmap(ScreenPtr screen, 1082 PixmapPtr pixmap, CARD16 *stride, CARD32 *size) 1083{ 1084 unsigned orig_usage_hint = pixmap->usage_hint; 1085 int ret; 1086 1087 /* 1088 * The actual difference between a shareable and non-shareable buffer 1089 * is decided 4 call levels deep in glamor_make_pixmap_exportable() 1090 * based on pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED 1091 * 2 of those calls are also exported API, so we cannot just add a flag. 1092 */ 1093 pixmap->usage_hint = CREATE_PIXMAP_USAGE_SHARED; 1094 1095 ret = glamor_fd_from_pixmap(screen, pixmap, stride, size); 1096 1097 pixmap->usage_hint = orig_usage_hint; 1098 return ret; 1099} 1100 1101int 1102glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size) 1103{ 1104 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 1105 1106 switch (pixmap_priv->type) { 1107 case GLAMOR_TEXTURE_DRM: 1108 case GLAMOR_TEXTURE_ONLY: 1109 if (!glamor_pixmap_ensure_fbo(pixmap, 0)) 1110 return -1; 1111 return glamor_egl_fd_name_from_pixmap(pixmap->drawable.pScreen, 1112 pixmap, stride, size); 1113 default: 1114 break; 1115 } 1116 return -1; 1117} 1118 1119void 1120glamor_finish(ScreenPtr screen) 1121{ 1122 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 1123 1124 glamor_make_current(glamor_priv); 1125 glFinish(); 1126} 1127