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 (at) anholt.net> 25 * Zhigang Gong <zhigang.gong (at) linux.intel.com> 26 * Chad Versace <chad.versace (at) 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 40 DevPrivateKeyRec glamor_screen_private_key; 41 DevPrivateKeyRec glamor_pixmap_private_key; 42 DevPrivateKeyRec glamor_gc_private_key; 43 44 glamor_screen_private * 45 glamor_get_screen_private(ScreenPtr screen) 46 { 47 return (glamor_screen_private *) 48 dixLookupPrivate(&screen->devPrivates, &glamor_screen_private_key); 49 } 50 51 void 52 glamor_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 */ 68 PixmapPtr 69 glamor_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 77 static void 78 glamor_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 93 glamor_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 103 glamor_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 133 glamor_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 149 uint32_t 150 glamor_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 166 void 167 glamor_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 201 PixmapPtr 202 glamor_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 || (glamor_priv->formats[depth].texture_only && 221 (usage != GLAMOR_CREATE_FBO_NO_FBO)))) 222 return fbCreatePixmap(screen, w, h, depth, usage); 223 else 224 pixmap = fbCreatePixmap(screen, 0, 0, depth, usage); 225 226 if (!pixmap) 227 return NullPixmap; 228 229 pixmap_priv = glamor_get_pixmap_private(pixmap); 230 231 pixmap_priv->is_cbcr = (GLAMOR_CREATE_FORMAT_CBCR & usage) == GLAMOR_CREATE_FORMAT_CBCR; 232 233 pitch = (((w * pixmap->drawable.bitsPerPixel + 7) / 8) + 3) & ~3; 234 screen->ModifyPixmapHeader(pixmap, w, h, 0, 0, pitch, NULL); 235 236 pixmap_priv->type = GLAMOR_TEXTURE_ONLY; 237 238 if (usage == GLAMOR_CREATE_PIXMAP_NO_TEXTURE) { 239 glamor_init_pixmap_private_small(pixmap, pixmap_priv); 240 return pixmap; 241 } 242 else if (usage == GLAMOR_CREATE_NO_LARGE || 243 glamor_check_fbo_size(glamor_priv, w, h)) 244 { 245 glamor_init_pixmap_private_small(pixmap, pixmap_priv); 246 fbo = glamor_create_fbo(glamor_priv, pixmap, w, h, usage); 247 } else { 248 int tile_size = glamor_priv->max_fbo_size; 249 DEBUGF("Create LARGE pixmap %p width %d height %d, tile size %d\n", 250 pixmap, w, h, tile_size); 251 fbo = glamor_create_fbo_array(glamor_priv, pixmap, usage, 252 tile_size, tile_size, pixmap_priv); 253 } 254 255 if (fbo == NULL) { 256 fbDestroyPixmap(pixmap); 257 return fbCreatePixmap(screen, w, h, depth, usage); 258 } 259 260 glamor_pixmap_attach_fbo(pixmap, fbo); 261 262 return pixmap; 263 } 264 265 Bool 266 glamor_destroy_pixmap(PixmapPtr pixmap) 267 { 268 if (pixmap->refcnt == 1) { 269 glamor_pixmap_destroy_fbo(pixmap); 270 } 271 272 return fbDestroyPixmap(pixmap); 273 } 274 275 void 276 glamor_block_handler(ScreenPtr screen) 277 { 278 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 279 280 glamor_make_current(glamor_priv); 281 glFlush(); 282 } 283 284 static void 285 _glamor_block_handler(ScreenPtr screen, void *timeout) 286 { 287 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 288 289 glamor_make_current(glamor_priv); 290 glFlush(); 291 292 screen->BlockHandler = glamor_priv->saved_procs.block_handler; 293 screen->BlockHandler(screen, timeout); 294 glamor_priv->saved_procs.block_handler = screen->BlockHandler; 295 screen->BlockHandler = _glamor_block_handler; 296 } 297 298 static void 299 glamor_set_debug_level(int *debug_level) 300 { 301 char *debug_level_string; 302 303 debug_level_string = getenv("GLAMOR_DEBUG"); 304 if (debug_level_string 305 && sscanf(debug_level_string, "%d", debug_level) == 1) 306 return; 307 *debug_level = 0; 308 } 309 310 int glamor_debug_level; 311 312 void 313 glamor_gldrawarrays_quads_using_indices(glamor_screen_private *glamor_priv, 314 unsigned count) 315 { 316 unsigned i; 317 318 /* If there is no quads to draw, just exit */ 319 if (count == 0) 320 return; 321 322 /* For a single quad, don't bother with an index buffer. */ 323 if (count == 1) 324 goto fallback; 325 326 if (glamor_priv->ib_size < count) { 327 /* Basic GLES2 doesn't have any way to map buffer objects for 328 * writing, but it's long past time for drivers to have 329 * MapBufferRange. 330 */ 331 if (!glamor_priv->has_map_buffer_range) 332 goto fallback; 333 334 /* Lazy create the buffer name, and only bind it once since 335 * none of the glamor code binds it to anything else. 336 */ 337 if (!glamor_priv->ib) { 338 glGenBuffers(1, &glamor_priv->ib); 339 glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, glamor_priv->ib); 340 } 341 342 /* For now, only support GL_UNSIGNED_SHORTs. */ 343 if (count > ((1 << 16) - 1) / 4) { 344 goto fallback; 345 } else { 346 uint16_t *data; 347 size_t size = count * 6 * sizeof(GLushort); 348 349 glBufferData(GL_ELEMENT_ARRAY_BUFFER, size, NULL, GL_STATIC_DRAW); 350 data = glMapBufferRange(GL_ELEMENT_ARRAY_BUFFER, 351 0, size, 352 GL_MAP_WRITE_BIT | 353 GL_MAP_INVALIDATE_BUFFER_BIT); 354 for (i = 0; i < count; i++) { 355 data[i * 6 + 0] = i * 4 + 0; 356 data[i * 6 + 1] = i * 4 + 1; 357 data[i * 6 + 2] = i * 4 + 2; 358 data[i * 6 + 3] = i * 4 + 0; 359 data[i * 6 + 4] = i * 4 + 2; 360 data[i * 6 + 5] = i * 4 + 3; 361 } 362 glUnmapBuffer(GL_ELEMENT_ARRAY_BUFFER); 363 364 glamor_priv->ib_size = count; 365 glamor_priv->ib_type = GL_UNSIGNED_SHORT; 366 } 367 } 368 369 glDrawElements(GL_TRIANGLES, count * 6, glamor_priv->ib_type, NULL); 370 return; 371 372 fallback: 373 for (i = 0; i < count; i++) 374 glDrawArrays(GL_TRIANGLE_FAN, i * 4, 4); 375 } 376 377 378 static void GLAPIENTRY 379 glamor_debug_output_callback(GLenum source, 380 GLenum type, 381 GLuint id, 382 GLenum severity, 383 GLsizei length, 384 const GLchar *message, 385 const void *userParam) 386 { 387 ScreenPtr screen = (void *)userParam; 388 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 389 390 if (glamor_priv->suppress_gl_out_of_memory_logging && 391 source == GL_DEBUG_SOURCE_API && type == GL_DEBUG_TYPE_ERROR) { 392 return; 393 } 394 395 LogMessageVerb(X_ERROR, 0, "glamor%d: GL error: %*s\n", 396 screen->myNum, length, message); 397 xorg_backtrace(); 398 } 399 400 /** 401 * Configures GL_ARB_debug_output to give us immediate callbacks when 402 * GL errors occur, so that we can log them. 403 */ 404 static void 405 glamor_setup_debug_output(ScreenPtr screen) 406 { 407 if (!epoxy_has_gl_extension("GL_KHR_debug") && 408 !epoxy_has_gl_extension("GL_ARB_debug_output")) 409 return; 410 411 glEnable(GL_DEBUG_OUTPUT_SYNCHRONOUS); 412 /* Disable debugging messages other than GL API errors */ 413 glDebugMessageControl(GL_DONT_CARE, GL_DONT_CARE, GL_DONT_CARE, 0, NULL, 414 GL_FALSE); 415 glDebugMessageControl(GL_DEBUG_SOURCE_API, 416 GL_DEBUG_TYPE_ERROR, 417 GL_DONT_CARE, 418 0, NULL, GL_TRUE); 419 glDebugMessageCallback(glamor_debug_output_callback, 420 screen); 421 422 /* If KHR_debug is present, all debug output is disabled by 423 * default on non-debug contexts. 424 */ 425 if (epoxy_has_gl_extension("GL_KHR_debug")) 426 glEnable(GL_DEBUG_OUTPUT); 427 } 428 429 const struct glamor_format * 430 glamor_format_for_pixmap(PixmapPtr pixmap) 431 { 432 ScreenPtr pScreen = pixmap->drawable.pScreen; 433 glamor_screen_private *glamor_priv = glamor_get_screen_private(pScreen); 434 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 435 436 if (pixmap_priv->is_cbcr) 437 return &glamor_priv->cbcr_format; 438 else 439 return &glamor_priv->formats[pixmap->drawable.depth]; 440 } 441 442 static void 443 glamor_add_format(ScreenPtr screen, int depth, CARD32 render_format, 444 GLenum internalformat, GLenum format, GLenum type, 445 Bool rendering_supported) 446 { 447 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 448 struct glamor_format *f = &glamor_priv->formats[depth]; 449 Bool texture_only = FALSE; 450 451 /* If we're trying to run on GLES, make sure that we get the read 452 * formats that we're expecting, since glamor_transfer relies on 453 * them matching to get data back out. To avoid this limitation, we 454 * would need to have a more general glReadPixels() path in 455 * glamor_transfer that re-encoded the bits to the pixel format that 456 * we intended after. 457 * 458 * Note that we can't just create a pixmap because we're in 459 * screeninit. 460 */ 461 if (rendering_supported && glamor_priv->is_gles) { 462 unsigned fbo, tex; 463 int read_format, read_type; 464 GLenum status; 465 466 glGenTextures(1, &tex); 467 glBindTexture(GL_TEXTURE_2D, tex); 468 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 469 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 470 glTexImage2D(GL_TEXTURE_2D, 0, internalformat, 1, 1, 0, 471 format, type, NULL); 472 if (glGetError() != GL_NO_ERROR) 473 { 474 ErrorF("glamor: Cannot upload texture for depth %d. " 475 "Falling back to software.\n", depth); 476 glDeleteTextures(1, &tex); 477 return; 478 } 479 480 glGenFramebuffers(1, &fbo); 481 glBindFramebuffer(GL_FRAMEBUFFER, fbo); 482 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, 483 GL_TEXTURE_2D, tex, 0); 484 status = glCheckFramebufferStatus(GL_FRAMEBUFFER); 485 if (status != GL_FRAMEBUFFER_COMPLETE) { 486 ErrorF("glamor: Test fbo for depth %d incomplete. " 487 "Falling back to software.\n", depth); 488 glDeleteTextures(1, &tex); 489 glDeleteFramebuffers(1, &fbo); 490 texture_only = TRUE; 491 } 492 493 if (!texture_only) { 494 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_FORMAT, &read_format); 495 glGetIntegerv(GL_IMPLEMENTATION_COLOR_READ_TYPE, &read_type); 496 } 497 498 glDeleteTextures(1, &tex); 499 glDeleteFramebuffers(1, &fbo); 500 501 if (!texture_only && (format != read_format || type != read_type)) { 502 ErrorF("glamor: Implementation returned 0x%x/0x%x read format/type " 503 "for depth %d, expected 0x%x/0x%x. " 504 "Falling back to software.\n", 505 read_format, read_type, depth, format, type); 506 texture_only = TRUE; 507 } 508 } 509 510 f->depth = depth; 511 f->render_format = render_format; 512 f->internalformat = internalformat; 513 f->format = format; 514 f->type = type; 515 f->rendering_supported = rendering_supported; 516 f->texture_only = texture_only; 517 } 518 519 /* Set up the GL format/types that glamor will use for the various depths 520 * 521 * X11's pixel data doesn't have channels, but to store our data in GL 522 * we have to pick some sort of format to move X11 pixel data in and 523 * out with in glamor_transfer.c. For X11 core operations, other than 524 * GL logic ops (non-GXcopy GC ops) what the driver chooses internally 525 * doesn't matter as long as it doesn't drop any bits (we expect them 526 * to generally expand, if anything). For Render, we can expect 527 * clients to tend to render with PictFormats matching our channel 528 * layouts here since ultimately X11 pixels tend to end up on the 529 * screen. The render implementation will fall back to fb if the 530 * channels don't match. 531 * 532 * Note that these formats don't affect what glamor_egl.c or 533 * Xwayland's EGL layer choose for surfaces exposed through DRI or 534 * scanout. For now, those layers need to match what we're choosing 535 * here, or channels will end up swizzled around. Similarly, the 536 * driver's visual masks also need to match what we're doing here. 537 */ 538 static void 539 glamor_setup_formats(ScreenPtr screen) 540 { 541 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 542 543 /* Prefer r8 textures since they're required by GLES3 and core, 544 * only falling back to a8 if we can't do them. We cannot do them 545 * on GLES2 due to lack of texture swizzle. 546 */ 547 if (glamor_priv->has_rg && glamor_priv->has_texture_swizzle) { 548 glamor_add_format(screen, 1, PICT_a1, 549 GL_R8, GL_RED, GL_UNSIGNED_BYTE, FALSE); 550 glamor_add_format(screen, 8, PICT_a8, 551 GL_R8, GL_RED, GL_UNSIGNED_BYTE, TRUE); 552 } else { 553 glamor_add_format(screen, 1, PICT_a1, 554 GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, FALSE); 555 glamor_add_format(screen, 8, PICT_a8, 556 GL_ALPHA, GL_ALPHA, GL_UNSIGNED_BYTE, TRUE); 557 } 558 559 if (glamor_priv->is_gles) { 560 /* For 15bpp, GLES supports format/type RGBA/5551, rather than 561 * bgra/1555_rev. GL_EXT_bgra lets the impl say the color 562 * read format/type is bgra/1555 even if we had to create it 563 * with rgba/5551, with Mesa does. That means we can't use 564 * the same format/type for TexSubImage and readpixels. 565 * 566 * Instead, just store 16 bits using the trusted 565 path, and 567 * disable render accel for now. 568 */ 569 glamor_add_format(screen, 15, PICT_x1r5g5b5, 570 GL_RGB5_A1, GL_RGBA, GL_UNSIGNED_SHORT_5_5_5_1, TRUE); 571 } else { 572 glamor_add_format(screen, 15, PICT_x1r5g5b5, 573 GL_RGBA, GL_BGRA, GL_UNSIGNED_SHORT_1_5_5_5_REV, TRUE); 574 } 575 576 glamor_add_format(screen, 16, PICT_r5g6b5, 577 GL_RGB, GL_RGB, GL_UNSIGNED_SHORT_5_6_5, TRUE); 578 579 if (glamor_priv->is_gles) { 580 assert(X_BYTE_ORDER == X_LITTLE_ENDIAN); 581 glamor_add_format(screen, 24, PICT_x8r8g8b8, 582 GL_BGRA, GL_BGRA, GL_UNSIGNED_BYTE, TRUE); 583 glamor_add_format(screen, 32, PICT_a8r8g8b8, 584 GL_BGRA, GL_BGRA, GL_UNSIGNED_BYTE, TRUE); 585 } else { 586 glamor_add_format(screen, 24, PICT_x8r8g8b8, 587 GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE); 588 glamor_add_format(screen, 32, PICT_a8r8g8b8, 589 GL_RGBA, GL_BGRA, GL_UNSIGNED_INT_8_8_8_8_REV, TRUE); 590 } 591 592 if (glamor_priv->is_gles) { 593 glamor_add_format(screen, 30, PICT_x2b10g10r10, 594 GL_RGB10_A2, GL_RGBA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE); 595 } else { 596 glamor_add_format(screen, 30, PICT_x2r10g10b10, 597 GL_RGB10_A2, GL_BGRA, GL_UNSIGNED_INT_2_10_10_10_REV, TRUE); 598 } 599 600 glamor_priv->cbcr_format.depth = 16; 601 if (glamor_priv->is_gles && glamor_priv->has_rg) { 602 glamor_priv->cbcr_format.internalformat = GL_RG; 603 } else { 604 glamor_priv->cbcr_format.internalformat = GL_RG8; 605 } 606 glamor_priv->cbcr_format.format = GL_RG; 607 glamor_priv->cbcr_format.render_format = PICT_yuv2; 608 glamor_priv->cbcr_format.type = GL_UNSIGNED_BYTE; 609 glamor_priv->cbcr_format.rendering_supported = TRUE; 610 glamor_priv->cbcr_format.texture_only = FALSE; 611 } 612 613 /** Set up glamor for an already-configured GL context. */ 614 Bool 615 glamor_init(ScreenPtr screen, unsigned int flags) 616 { 617 glamor_screen_private *glamor_priv; 618 int gl_version; 619 int glsl_major, glsl_minor; 620 int max_viewport_size[2]; 621 const char *shading_version_string; 622 int shading_version_offset; 623 624 PictureScreenPtr ps = GetPictureScreenIfSet(screen); 625 626 if (flags & ~GLAMOR_VALID_FLAGS) { 627 ErrorF("glamor_init: Invalid flags %x\n", flags); 628 return FALSE; 629 } 630 glamor_priv = calloc(1, sizeof(*glamor_priv)); 631 if (glamor_priv == NULL) 632 return FALSE; 633 634 glamor_priv->flags = flags; 635 636 if (!dixRegisterPrivateKey(&glamor_screen_private_key, PRIVATE_SCREEN, 0)) { 637 LogMessage(X_WARNING, 638 "glamor%d: Failed to allocate screen private\n", 639 screen->myNum); 640 goto free_glamor_private; 641 } 642 643 glamor_set_screen_private(screen, glamor_priv); 644 645 if (!dixRegisterPrivateKey(&glamor_pixmap_private_key, PRIVATE_PIXMAP, 646 sizeof(struct glamor_pixmap_private))) { 647 LogMessage(X_WARNING, 648 "glamor%d: Failed to allocate pixmap private\n", 649 screen->myNum); 650 goto free_glamor_private; 651 } 652 653 if (!dixRegisterPrivateKey(&glamor_gc_private_key, PRIVATE_GC, 654 sizeof (glamor_gc_private))) { 655 LogMessage(X_WARNING, 656 "glamor%d: Failed to allocate gc private\n", 657 screen->myNum); 658 goto free_glamor_private; 659 } 660 661 glamor_priv->saved_procs.close_screen = screen->CloseScreen; 662 screen->CloseScreen = glamor_close_screen; 663 664 glamor_priv->saved_procs.destroy_pixmap = screen->DestroyPixmap; 665 screen->DestroyPixmap = glamor_destroy_pixmap; 666 667 /* If we are using egl screen, call egl screen init to 668 * register correct close screen function. */ 669 if (flags & GLAMOR_USE_EGL_SCREEN) { 670 glamor_egl_screen_init(screen, &glamor_priv->ctx); 671 } else { 672 if (!glamor_glx_screen_init(&glamor_priv->ctx)) 673 goto fail; 674 } 675 676 glamor_make_current(glamor_priv); 677 678 if (!epoxy_is_desktop_gl()) 679 glamor_priv->is_gles = TRUE; 680 681 gl_version = epoxy_gl_version(); 682 683 /* assume a core profile if we are GL 3.1 and don't have ARB_compatibility */ 684 glamor_priv->is_core_profile = 685 gl_version >= 31 && !epoxy_has_gl_extension("GL_ARB_compatibility"); 686 687 shading_version_string = (char *) glGetString(GL_SHADING_LANGUAGE_VERSION); 688 689 if (!shading_version_string) { 690 LogMessage(X_WARNING, 691 "glamor%d: Failed to get GLSL version\n", 692 screen->myNum); 693 goto fail; 694 } 695 696 shading_version_offset = 0; 697 if (strncmp("OpenGL ES GLSL ES ", shading_version_string, 18) == 0) 698 shading_version_offset = 18; 699 700 if (sscanf(shading_version_string + shading_version_offset, 701 "%i.%i", 702 &glsl_major, 703 &glsl_minor) != 2) { 704 LogMessage(X_WARNING, 705 "glamor%d: Failed to parse GLSL version string %s\n", 706 screen->myNum, shading_version_string); 707 goto fail; 708 } 709 glamor_priv->glsl_version = glsl_major * 100 + glsl_minor; 710 711 /* We'd like to require GL_ARB_map_buffer_range or 712 * GL_OES_map_buffer_range, since it offers more information to 713 * the driver than plain old glMapBuffer() or glBufferSubData(). 714 * It's been supported on Mesa on the desktop since 2009 and on 715 * GLES2 since October 2012. It's supported on Apple's iOS 716 * drivers for SGX535 and A7, but apparently not on most Android 717 * devices (the OES extension spec wasn't released until June 718 * 2012). 719 * 720 * 82% of 0 A.D. players (desktop GL) submitting hardware reports 721 * have support for it, with most of the ones lacking it being on 722 * Windows with Intel 4-series (G45) graphics or older. 723 */ 724 if (!glamor_priv->is_gles) { 725 if (gl_version < 21) { 726 ErrorF("Require OpenGL version 2.1 or later.\n"); 727 goto fail; 728 } 729 730 if (!glamor_priv->is_core_profile && 731 !epoxy_has_gl_extension("GL_ARB_texture_border_clamp")) { 732 ErrorF("GL_ARB_texture_border_clamp required\n"); 733 goto fail; 734 } 735 736 /* Glamor rendering assumes that platforms with GLSL 130+ 737 * have instanced arrays, but this is not always the case. 738 * etnaviv offers GLSL 140 with OpenGL 2.1. 739 */ 740 if (glamor_glsl_has_ints(glamor_priv) && 741 !glamor_priv->is_gles && 742 !epoxy_has_gl_extension("GL_ARB_instanced_arrays")) 743 glamor_priv->glsl_version = 120; 744 } else { 745 if (gl_version < 20) { 746 ErrorF("Require Open GLES2.0 or later.\n"); 747 goto fail; 748 } 749 750 if (!epoxy_has_gl_extension("GL_EXT_texture_format_BGRA8888")) { 751 ErrorF("GL_EXT_texture_format_BGRA8888 required\n"); 752 goto fail; 753 } 754 755 if (!epoxy_has_gl_extension("GL_OES_texture_border_clamp")) { 756 ErrorF("GL_OES_texture_border_clamp required\n"); 757 goto fail; 758 } 759 } 760 761 if (!epoxy_has_gl_extension("GL_ARB_vertex_array_object") && 762 !epoxy_has_gl_extension("GL_OES_vertex_array_object")) { 763 ErrorF("GL_{ARB,OES}_vertex_array_object required\n"); 764 goto fail; 765 } 766 767 if (!glamor_priv->is_gles && glamor_priv->glsl_version == 120 && 768 epoxy_has_gl_extension("GL_ARB_instanced_arrays")) 769 glamor_priv->use_gpu_shader4 = epoxy_has_gl_extension("GL_EXT_gpu_shader4"); 770 771 glamor_priv->has_rw_pbo = FALSE; 772 if (!glamor_priv->is_gles) 773 glamor_priv->has_rw_pbo = TRUE; 774 775 glamor_priv->has_khr_debug = epoxy_has_gl_extension("GL_KHR_debug"); 776 glamor_priv->has_pack_invert = 777 epoxy_has_gl_extension("GL_MESA_pack_invert"); 778 glamor_priv->has_fbo_blit = 779 epoxy_has_gl_extension("GL_EXT_framebuffer_blit"); 780 glamor_priv->has_map_buffer_range = 781 epoxy_has_gl_extension("GL_ARB_map_buffer_range") || 782 epoxy_has_gl_extension("GL_EXT_map_buffer_range"); 783 glamor_priv->has_buffer_storage = 784 epoxy_has_gl_extension("GL_ARB_buffer_storage"); 785 glamor_priv->has_mesa_tile_raster_order = 786 epoxy_has_gl_extension("GL_MESA_tile_raster_order"); 787 glamor_priv->has_nv_texture_barrier = 788 epoxy_has_gl_extension("GL_NV_texture_barrier"); 789 glamor_priv->has_unpack_subimage = 790 !glamor_priv->is_gles || 791 epoxy_gl_version() >= 30 || 792 epoxy_has_gl_extension("GL_EXT_unpack_subimage"); 793 glamor_priv->has_pack_subimage = 794 !glamor_priv->is_gles || 795 epoxy_gl_version() >= 30 || 796 epoxy_has_gl_extension("GL_NV_pack_subimage"); 797 glamor_priv->has_dual_blend = 798 (epoxy_has_gl_extension("GL_ARB_blend_func_extended") && 799 (glamor_glsl_has_ints(glamor_priv) || 800 epoxy_has_gl_extension("GL_ARB_ES2_compatibility"))) || 801 epoxy_has_gl_extension("GL_EXT_blend_func_extended"); 802 glamor_priv->has_clear_texture = 803 epoxy_gl_version() >= 44 || 804 epoxy_has_gl_extension("GL_ARB_clear_texture"); 805 /* GL_EXT_texture_rg is part of GLES3 core */ 806 glamor_priv->has_rg = 807 (glamor_priv->is_gles && epoxy_gl_version() >= 30) || 808 epoxy_has_gl_extension("GL_EXT_texture_rg") || 809 epoxy_has_gl_extension("GL_ARB_texture_rg"); 810 811 glamor_priv->can_copyplane = (gl_version >= 30); 812 813 glamor_setup_debug_output(screen); 814 815 glamor_priv->use_quads = !glamor_priv->is_gles && 816 !glamor_priv->is_core_profile; 817 818 /* Driver-specific hack: Avoid using GL_QUADS on VC4, where 819 * they'll be emulated more expensively than we can with our 820 * cached IB. 821 */ 822 if (strstr((char *)glGetString(GL_VENDOR), "Broadcom") && 823 (strstr((char *)glGetString(GL_RENDERER), "VC4") || 824 strstr((char *)glGetString(GL_RENDERER), "V3D"))) 825 glamor_priv->use_quads = FALSE; 826 827 glGetIntegerv(GL_MAX_RENDERBUFFER_SIZE, &glamor_priv->max_fbo_size); 828 glGetIntegerv(GL_MAX_TEXTURE_SIZE, &glamor_priv->max_fbo_size); 829 glGetIntegerv(GL_MAX_VIEWPORT_DIMS, max_viewport_size); 830 glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[0]); 831 glamor_priv->max_fbo_size = MIN(glamor_priv->max_fbo_size, max_viewport_size[1]); 832 #ifdef MAX_FBO_SIZE 833 glamor_priv->max_fbo_size = MAX_FBO_SIZE; 834 #endif 835 836 glamor_priv->has_texture_swizzle = 837 (epoxy_has_gl_extension("GL_ARB_texture_swizzle") || 838 (glamor_priv->is_gles && gl_version >= 30)); 839 840 glamor_setup_formats(screen); 841 842 glamor_set_debug_level(&glamor_debug_level); 843 844 if (!glamor_font_init(screen)) 845 goto fail; 846 847 glamor_priv->saved_procs.block_handler = screen->BlockHandler; 848 screen->BlockHandler = _glamor_block_handler; 849 850 if (!glamor_composite_glyphs_init(screen)) { 851 ErrorF("Failed to initialize composite masks\n"); 852 goto fail; 853 } 854 855 glamor_priv->saved_procs.create_gc = screen->CreateGC; 856 screen->CreateGC = glamor_create_gc; 857 858 glamor_priv->saved_procs.create_pixmap = screen->CreatePixmap; 859 screen->CreatePixmap = glamor_create_pixmap; 860 861 glamor_priv->saved_procs.get_spans = screen->GetSpans; 862 screen->GetSpans = glamor_get_spans; 863 864 glamor_priv->saved_procs.get_image = screen->GetImage; 865 screen->GetImage = glamor_get_image; 866 867 glamor_priv->saved_procs.change_window_attributes = 868 screen->ChangeWindowAttributes; 869 screen->ChangeWindowAttributes = glamor_change_window_attributes; 870 871 glamor_priv->saved_procs.copy_window = screen->CopyWindow; 872 screen->CopyWindow = glamor_copy_window; 873 874 glamor_priv->saved_procs.bitmap_to_region = screen->BitmapToRegion; 875 screen->BitmapToRegion = glamor_bitmap_to_region; 876 877 if (ps) { 878 glamor_priv->saved_procs.composite = ps->Composite; 879 ps->Composite = glamor_composite; 880 881 glamor_priv->saved_procs.trapezoids = ps->Trapezoids; 882 ps->Trapezoids = glamor_trapezoids; 883 884 glamor_priv->saved_procs.triangles = ps->Triangles; 885 ps->Triangles = glamor_triangles; 886 887 glamor_priv->saved_procs.addtraps = ps->AddTraps; 888 ps->AddTraps = glamor_add_traps; 889 890 glamor_priv->saved_procs.composite_rects = ps->CompositeRects; 891 ps->CompositeRects = glamor_composite_rectangles; 892 893 glamor_priv->saved_procs.glyphs = ps->Glyphs; 894 ps->Glyphs = glamor_composite_glyphs; 895 } 896 897 glamor_init_vbo(screen); 898 899 glamor_priv->enable_gradient_shader = TRUE; 900 901 if (!glamor_init_gradient_shader(screen)) { 902 LogMessage(X_WARNING, 903 "glamor%d: Cannot initialize gradient shader, falling back to software rendering for gradients\n", 904 screen->myNum); 905 glamor_priv->enable_gradient_shader = FALSE; 906 } 907 908 glamor_pixmap_init(screen); 909 glamor_sync_init(screen); 910 911 glamor_priv->screen = screen; 912 913 return TRUE; 914 915 fail: 916 /* Restore default CloseScreen and DestroyPixmap handlers */ 917 screen->CloseScreen = glamor_priv->saved_procs.close_screen; 918 screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; 919 920 free_glamor_private: 921 free(glamor_priv); 922 glamor_set_screen_private(screen, NULL); 923 return FALSE; 924 } 925 926 static void 927 glamor_release_screen_priv(ScreenPtr screen) 928 { 929 glamor_screen_private *glamor_priv; 930 931 glamor_priv = glamor_get_screen_private(screen); 932 glamor_fini_vbo(screen); 933 glamor_pixmap_fini(screen); 934 free(glamor_priv); 935 936 glamor_set_screen_private(screen, NULL); 937 } 938 939 Bool 940 glamor_close_screen(ScreenPtr screen) 941 { 942 glamor_screen_private *glamor_priv; 943 PixmapPtr screen_pixmap; 944 PictureScreenPtr ps = GetPictureScreenIfSet(screen); 945 946 glamor_priv = glamor_get_screen_private(screen); 947 glamor_sync_close(screen); 948 glamor_composite_glyphs_fini(screen); 949 screen->CloseScreen = glamor_priv->saved_procs.close_screen; 950 951 screen->CreateGC = glamor_priv->saved_procs.create_gc; 952 screen->CreatePixmap = glamor_priv->saved_procs.create_pixmap; 953 screen->DestroyPixmap = glamor_priv->saved_procs.destroy_pixmap; 954 screen->GetSpans = glamor_priv->saved_procs.get_spans; 955 screen->ChangeWindowAttributes = 956 glamor_priv->saved_procs.change_window_attributes; 957 screen->CopyWindow = glamor_priv->saved_procs.copy_window; 958 screen->BitmapToRegion = glamor_priv->saved_procs.bitmap_to_region; 959 screen->BlockHandler = glamor_priv->saved_procs.block_handler; 960 961 if (ps) { 962 ps->Composite = glamor_priv->saved_procs.composite; 963 ps->Trapezoids = glamor_priv->saved_procs.trapezoids; 964 ps->Triangles = glamor_priv->saved_procs.triangles; 965 ps->CompositeRects = glamor_priv->saved_procs.composite_rects; 966 ps->Glyphs = glamor_priv->saved_procs.glyphs; 967 } 968 969 screen_pixmap = screen->GetScreenPixmap(screen); 970 glamor_pixmap_destroy_fbo(screen_pixmap); 971 972 glamor_release_screen_priv(screen); 973 974 return screen->CloseScreen(screen); 975 } 976 977 void 978 glamor_fini(ScreenPtr screen) 979 { 980 /* Do nothing currently. */ 981 } 982 983 void 984 glamor_enable_dri3(ScreenPtr screen) 985 { 986 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 987 988 glamor_priv->dri3_enabled = TRUE; 989 } 990 991 Bool 992 glamor_supports_pixmap_import_export(ScreenPtr screen) 993 { 994 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 995 996 return glamor_priv->dri3_enabled; 997 } 998 999 _X_EXPORT void 1000 glamor_set_drawable_modifiers_func(ScreenPtr screen, 1001 GetDrawableModifiersFuncPtr func) 1002 { 1003 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 1004 1005 glamor_priv->get_drawable_modifiers = func; 1006 } 1007 1008 _X_EXPORT Bool 1009 glamor_get_drawable_modifiers(DrawablePtr draw, uint32_t format, 1010 uint32_t *num_modifiers, uint64_t **modifiers) 1011 { 1012 struct glamor_screen_private *glamor_priv = 1013 glamor_get_screen_private(draw->pScreen); 1014 1015 if (glamor_priv->get_drawable_modifiers) { 1016 return glamor_priv->get_drawable_modifiers(draw, format, 1017 num_modifiers, modifiers); 1018 } 1019 *num_modifiers = 0; 1020 *modifiers = NULL; 1021 return TRUE; 1022 } 1023 1024 static int 1025 _glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, 1026 uint32_t *strides, uint32_t *offsets, 1027 CARD32 *size, uint64_t *modifier) 1028 { 1029 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 1030 glamor_screen_private *glamor_priv = 1031 glamor_get_screen_private(pixmap->drawable.pScreen); 1032 1033 if (!glamor_priv->dri3_enabled) 1034 return 0; 1035 switch (pixmap_priv->type) { 1036 case GLAMOR_TEXTURE_DRM: 1037 case GLAMOR_TEXTURE_ONLY: 1038 if (!glamor_pixmap_ensure_fbo(pixmap, 0)) 1039 return 0; 1040 1041 if (modifier) { 1042 return glamor_egl_fds_from_pixmap(screen, pixmap, fds, 1043 strides, offsets, 1044 modifier); 1045 } else { 1046 CARD16 stride; 1047 1048 fds[0] = glamor_egl_fd_from_pixmap(screen, pixmap, &stride, size); 1049 strides[0] = stride; 1050 1051 return fds[0] >= 0; 1052 } 1053 default: 1054 break; 1055 } 1056 return 0; 1057 } 1058 1059 _X_EXPORT int 1060 glamor_fds_from_pixmap(ScreenPtr screen, PixmapPtr pixmap, int *fds, 1061 uint32_t *strides, uint32_t *offsets, 1062 uint64_t *modifier) 1063 { 1064 return _glamor_fds_from_pixmap(screen, pixmap, fds, strides, offsets, 1065 NULL, modifier); 1066 } 1067 1068 _X_EXPORT int 1069 glamor_fd_from_pixmap(ScreenPtr screen, 1070 PixmapPtr pixmap, CARD16 *stride, CARD32 *size) 1071 { 1072 int fd; 1073 int ret; 1074 uint32_t stride32; 1075 1076 ret = _glamor_fds_from_pixmap(screen, pixmap, &fd, &stride32, NULL, size, 1077 NULL); 1078 if (ret != 1) 1079 return -1; 1080 1081 *stride = stride32; 1082 return fd; 1083 } 1084 1085 _X_EXPORT int 1086 glamor_shareable_fd_from_pixmap(ScreenPtr screen, 1087 PixmapPtr pixmap, CARD16 *stride, CARD32 *size) 1088 { 1089 unsigned orig_usage_hint = pixmap->usage_hint; 1090 int ret; 1091 1092 /* 1093 * The actual difference between a shareable and non-shareable buffer 1094 * is decided 4 call levels deep in glamor_make_pixmap_exportable() 1095 * based on pixmap->usage_hint == CREATE_PIXMAP_USAGE_SHARED 1096 * 2 of those calls are also exported API, so we cannot just add a flag. 1097 */ 1098 pixmap->usage_hint = CREATE_PIXMAP_USAGE_SHARED; 1099 1100 ret = glamor_fd_from_pixmap(screen, pixmap, stride, size); 1101 1102 pixmap->usage_hint = orig_usage_hint; 1103 return ret; 1104 } 1105 1106 int 1107 glamor_name_from_pixmap(PixmapPtr pixmap, CARD16 *stride, CARD32 *size) 1108 { 1109 glamor_pixmap_private *pixmap_priv = glamor_get_pixmap_private(pixmap); 1110 1111 switch (pixmap_priv->type) { 1112 case GLAMOR_TEXTURE_DRM: 1113 case GLAMOR_TEXTURE_ONLY: 1114 if (!glamor_pixmap_ensure_fbo(pixmap, 0)) 1115 return -1; 1116 return glamor_egl_fd_name_from_pixmap(pixmap->drawable.pScreen, 1117 pixmap, stride, size); 1118 default: 1119 break; 1120 } 1121 return -1; 1122 } 1123 1124 void 1125 glamor_finish(ScreenPtr screen) 1126 { 1127 glamor_screen_private *glamor_priv = glamor_get_screen_private(screen); 1128 1129 glamor_make_current(glamor_priv); 1130 glFinish(); 1131 } 1132