1 /************************************************************************** 2 * 3 * Copyright (C) 2014 Red Hat Inc. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the "Software"), 7 * to deal in the Software without restriction, including without limitation 8 * the rights to use, copy, modify, merge, publish, distribute, sublicense, 9 * and/or sell copies of the Software, and to permit persons to whom the 10 * Software is furnished to do so, subject to the following conditions: 11 * 12 * The above copyright notice and this permission notice shall be included 13 * in all copies or substantial portions of the Software. 14 * 15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 16 * OR 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 19 * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, 20 * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 21 * OTHER DEALINGS IN THE SOFTWARE. 22 * 23 **************************************************************************/ 24 25 /* gallium blitter implementation in GL */ 26 /* for when we can't use glBlitFramebuffer */ 27 #include <epoxy/gl.h> 28 29 #include <stdio.h> 30 #include "pipe/p_shader_tokens.h" 31 32 #include "pipe/p_context.h" 33 #include "pipe/p_defines.h" 34 #include "pipe/p_screen.h" 35 #include "pipe/p_state.h" 36 #include "util/u_inlines.h" 37 #include "util/u_memory.h" 38 #include "util/u_dual_blend.h" 39 40 #include "util/u_double_list.h" 41 #include "util/u_format.h" 42 #include "util/u_texture.h" 43 #include "tgsi/tgsi_parse.h" 44 45 #include "vrend_object.h" 46 #include "vrend_shader.h" 47 48 #include "vrend_renderer.h" 49 50 #include "vrend_blitter.h" 51 52 #define DEST_SWIZZLE_SNIPPET_SIZE 64 53 54 struct vrend_blitter_ctx { 55 virgl_gl_context gl_context; 56 bool initialised; 57 bool use_gles; 58 int framebuffer_srgb_enabled; 59 60 GLuint vaoid; 61 62 GLuint vs; 63 GLuint vs_pos_only; 64 GLuint fs_texfetch_col[PIPE_MAX_TEXTURE_TYPES]; 65 GLuint fs_texfetch_depth[PIPE_MAX_TEXTURE_TYPES]; 66 GLuint fs_texfetch_depth_msaa[PIPE_MAX_TEXTURE_TYPES]; 67 GLuint fs_texfetch_col_swizzle; 68 GLuint fb_id; 69 70 unsigned dst_width; 71 unsigned dst_height; 72 73 GLuint vbo_id; 74 GLfloat vertices[4][2][4]; /**< {pos, color} or {pos, texcoord} */ 75 }; 76 77 static struct vrend_blitter_ctx vrend_blit_ctx; 78 79 struct vrend_blitter_point { 80 int x; 81 int y; 82 }; 83 84 struct vrend_blitter_delta { 85 int dx; 86 int dy; 87 }; 88 89 static bool build_and_check(GLuint id, const char *buf) 90 { 91 GLint param; 92 glShaderSource(id, 1, (const char **)&buf, NULL); 93 glCompileShader(id); 94 95 glGetShaderiv(id, GL_COMPILE_STATUS, ¶m); 96 if (param == GL_FALSE) { 97 char infolog[65536]; 98 int len; 99 glGetShaderInfoLog(id, 65536, &len, infolog); 100 fprintf(stderr,"shader failed to compile\n%s\n", infolog); 101 fprintf(stderr,"GLSL:\n%s\n", buf); 102 return false; 103 } 104 return true; 105 } 106 107 static bool blit_build_vs_passthrough(struct vrend_blitter_ctx *blit_ctx) 108 { 109 blit_ctx->vs = glCreateShader(GL_VERTEX_SHADER); 110 111 if (!build_and_check(blit_ctx->vs, 112 blit_ctx->use_gles ? VS_PASSTHROUGH_GLES : VS_PASSTHROUGH_GL)) { 113 glDeleteShader(blit_ctx->vs); 114 blit_ctx->vs = 0; 115 return false; 116 } 117 return true; 118 } 119 120 static void create_dest_swizzle_snippet(const uint8_t swizzle[4], 121 char snippet[DEST_SWIZZLE_SNIPPET_SIZE]) 122 { 123 static const uint8_t invalid_swizzle = 0xff; 124 ssize_t si = 0; 125 uint8_t inverse[4] = {invalid_swizzle, invalid_swizzle, invalid_swizzle, 126 invalid_swizzle}; 127 128 for (int i = 0; i < 4; ++i) { 129 if (swizzle[i] > 3) continue; 130 if (inverse[swizzle[i]] == invalid_swizzle) 131 inverse[swizzle[i]] = i; 132 } 133 134 for (int i = 0; i < 4; ++i) { 135 int res = -1; 136 if (inverse[i] > 3) { 137 /* Use 0.0f for unused color values, 1.0f for an unused alpha value */ 138 res = snprintf(&snippet[si], DEST_SWIZZLE_SNIPPET_SIZE - si, 139 i < 3 ? "0.0f, " : "1.0f"); 140 } else { 141 res = snprintf(&snippet[si], DEST_SWIZZLE_SNIPPET_SIZE - si, 142 "texel.%c%s", "rgba"[inverse[i]], i < 3 ? ", " : ""); 143 } 144 si += res > 0 ? res : 0; 145 } 146 } 147 148 static const char *vec4_type_for_tgsi_ret(enum tgsi_return_type tgsi_ret) 149 { 150 switch (tgsi_ret) { 151 case TGSI_RETURN_TYPE_SINT: return "ivec4"; 152 case TGSI_RETURN_TYPE_UINT: return "uvec4"; 153 default: return "vec4"; 154 } 155 } 156 157 static enum tgsi_return_type tgsi_ret_for_format(enum virgl_formats format) 158 { 159 if (util_format_is_pure_uint(format)) 160 return TGSI_RETURN_TYPE_UINT; 161 else if (util_format_is_pure_sint(format)) 162 return TGSI_RETURN_TYPE_SINT; 163 164 return TGSI_RETURN_TYPE_UNORM; 165 } 166 167 static GLuint blit_build_frag_tex_col(struct vrend_blitter_ctx *blit_ctx, 168 int tgsi_tex_target, 169 enum tgsi_return_type tgsi_ret, 170 const uint8_t swizzle[4]) 171 { 172 GLuint fs_id; 173 char shader_buf[4096]; 174 int is_shad; 175 const char *twm; 176 const char *ext_str = ""; 177 char dest_swizzle_snippet[DEST_SWIZZLE_SNIPPET_SIZE] = "texel"; 178 switch (tgsi_tex_target) { 179 case TGSI_TEXTURE_1D: 180 case TGSI_TEXTURE_BUFFER: 181 twm = ".x"; 182 break; 183 case TGSI_TEXTURE_1D_ARRAY: 184 case TGSI_TEXTURE_2D: 185 case TGSI_TEXTURE_RECT: 186 case TGSI_TEXTURE_2D_MSAA: 187 default: 188 twm = ".xy"; 189 break; 190 case TGSI_TEXTURE_SHADOW1D: 191 case TGSI_TEXTURE_SHADOW2D: 192 case TGSI_TEXTURE_SHADOW1D_ARRAY: 193 case TGSI_TEXTURE_SHADOWRECT: 194 case TGSI_TEXTURE_3D: 195 case TGSI_TEXTURE_CUBE: 196 case TGSI_TEXTURE_2D_ARRAY: 197 case TGSI_TEXTURE_2D_ARRAY_MSAA: 198 twm = ".xyz"; 199 break; 200 case TGSI_TEXTURE_SHADOWCUBE: 201 case TGSI_TEXTURE_SHADOW2D_ARRAY: 202 case TGSI_TEXTURE_SHADOWCUBE_ARRAY: 203 case TGSI_TEXTURE_CUBE_ARRAY: 204 twm = ""; 205 break; 206 } 207 208 if (tgsi_tex_target == TGSI_TEXTURE_CUBE_ARRAY || 209 tgsi_tex_target == TGSI_TEXTURE_SHADOWCUBE_ARRAY) 210 ext_str = "#extension GL_ARB_texture_cube_map_array : require\n"; 211 212 if (swizzle) 213 create_dest_swizzle_snippet(swizzle, dest_swizzle_snippet); 214 215 snprintf(shader_buf, 4096, blit_ctx->use_gles ? FS_TEXFETCH_COL_GLES : FS_TEXFETCH_COL_GL, 216 ext_str, vec4_type_for_tgsi_ret(tgsi_ret), 217 vrend_shader_samplerreturnconv(tgsi_ret), 218 vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm, 219 dest_swizzle_snippet); 220 221 fs_id = glCreateShader(GL_FRAGMENT_SHADER); 222 223 if (!build_and_check(fs_id, shader_buf)) { 224 glDeleteShader(fs_id); 225 return 0; 226 } 227 228 return fs_id; 229 } 230 231 static GLuint blit_build_frag_tex_col_msaa(struct vrend_blitter_ctx *blit_ctx, 232 int tgsi_tex_target, 233 enum tgsi_return_type tgsi_ret, 234 const uint8_t swizzle[4], 235 int nr_samples) 236 { 237 GLuint fs_id; 238 char shader_buf[4096]; 239 int is_shad; 240 const char *twm; 241 const char *ivec; 242 char dest_swizzle_snippet[DEST_SWIZZLE_SNIPPET_SIZE] = "texel"; 243 const char *ext_str = blit_ctx->use_gles ? "" : 244 "#extension GL_ARB_texture_multisample : enable\n"; 245 246 switch (tgsi_tex_target) { 247 case TGSI_TEXTURE_2D_MSAA: 248 twm = ".xy"; 249 ivec = "ivec2"; 250 break; 251 case TGSI_TEXTURE_2D_ARRAY_MSAA: 252 twm = ".xyz"; 253 ivec = "ivec3"; 254 break; 255 default: 256 return 0; 257 } 258 259 if (swizzle) 260 create_dest_swizzle_snippet(swizzle, dest_swizzle_snippet); 261 262 snprintf(shader_buf, 4096, 263 blit_ctx->use_gles ? FS_TEXFETCH_COL_MSAA_GLES : FS_TEXFETCH_COL_MSAA_GL, 264 ext_str, vec4_type_for_tgsi_ret(tgsi_ret), 265 vrend_shader_samplerreturnconv(tgsi_ret), 266 vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), 267 nr_samples, ivec, twm, dest_swizzle_snippet); 268 269 fs_id = glCreateShader(GL_FRAGMENT_SHADER); 270 271 if (!build_and_check(fs_id, shader_buf)) { 272 glDeleteShader(fs_id); 273 return 0; 274 } 275 276 return fs_id; 277 } 278 279 static GLuint blit_build_frag_tex_writedepth(struct vrend_blitter_ctx *blit_ctx, int tgsi_tex_target) 280 { 281 GLuint fs_id; 282 char shader_buf[4096]; 283 int is_shad; 284 const char *twm; 285 286 switch (tgsi_tex_target) { 287 case TGSI_TEXTURE_1D: 288 case TGSI_TEXTURE_BUFFER: 289 twm = ".x"; 290 break; 291 case TGSI_TEXTURE_1D_ARRAY: 292 case TGSI_TEXTURE_2D: 293 case TGSI_TEXTURE_RECT: 294 case TGSI_TEXTURE_2D_MSAA: 295 default: 296 twm = ".xy"; 297 break; 298 case TGSI_TEXTURE_SHADOW1D: 299 case TGSI_TEXTURE_SHADOW2D: 300 case TGSI_TEXTURE_SHADOW1D_ARRAY: 301 case TGSI_TEXTURE_SHADOWRECT: 302 case TGSI_TEXTURE_3D: 303 case TGSI_TEXTURE_CUBE: 304 case TGSI_TEXTURE_2D_ARRAY: 305 case TGSI_TEXTURE_2D_ARRAY_MSAA: 306 twm = ".xyz"; 307 break; 308 case TGSI_TEXTURE_SHADOWCUBE: 309 case TGSI_TEXTURE_SHADOW2D_ARRAY: 310 case TGSI_TEXTURE_SHADOWCUBE_ARRAY: 311 case TGSI_TEXTURE_CUBE_ARRAY: 312 twm = ""; 313 break; 314 } 315 316 snprintf(shader_buf, 4096, blit_ctx->use_gles ? FS_TEXFETCH_DS_GLES : FS_TEXFETCH_DS_GL, 317 vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), twm); 318 319 fs_id = glCreateShader(GL_FRAGMENT_SHADER); 320 321 if (!build_and_check(fs_id, shader_buf)) { 322 glDeleteShader(fs_id); 323 return 0; 324 } 325 326 return fs_id; 327 } 328 329 static GLuint blit_build_frag_blit_msaa_depth(struct vrend_blitter_ctx *blit_ctx, int tgsi_tex_target) 330 { 331 GLuint fs_id; 332 char shader_buf[4096]; 333 int is_shad; 334 const char *twm; 335 const char *ivec; 336 337 switch (tgsi_tex_target) { 338 case TGSI_TEXTURE_2D_MSAA: 339 twm = ".xy"; 340 ivec = "ivec2"; 341 break; 342 case TGSI_TEXTURE_2D_ARRAY_MSAA: 343 twm = ".xyz"; 344 ivec = "ivec3"; 345 break; 346 default: 347 return 0; 348 } 349 350 snprintf(shader_buf, 4096, blit_ctx->use_gles ? FS_TEXFETCH_DS_MSAA_GLES : FS_TEXFETCH_DS_MSAA_GL, 351 vrend_shader_samplertypeconv(tgsi_tex_target, &is_shad), ivec, twm); 352 353 fs_id = glCreateShader(GL_FRAGMENT_SHADER); 354 355 if (!build_and_check(fs_id, shader_buf)) { 356 glDeleteShader(fs_id); 357 return 0; 358 } 359 360 return fs_id; 361 } 362 363 static GLuint blit_get_frag_tex_writedepth(struct vrend_blitter_ctx *blit_ctx, int pipe_tex_target, unsigned nr_samples) 364 { 365 assert(pipe_tex_target < PIPE_MAX_TEXTURE_TYPES); 366 367 if (nr_samples > 1) { 368 GLuint *shader = &blit_ctx->fs_texfetch_depth_msaa[pipe_tex_target]; 369 370 if (!*shader) { 371 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, nr_samples); 372 373 *shader = blit_build_frag_blit_msaa_depth(blit_ctx, tgsi_tex); 374 } 375 return *shader; 376 377 } else { 378 GLuint *shader = &blit_ctx->fs_texfetch_depth[pipe_tex_target]; 379 380 if (!*shader) { 381 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, 0); 382 383 *shader = blit_build_frag_tex_writedepth(blit_ctx, tgsi_tex); 384 } 385 return *shader; 386 } 387 } 388 389 static GLuint blit_get_frag_tex_col(struct vrend_blitter_ctx *blit_ctx, 390 int pipe_tex_target, 391 unsigned nr_samples, 392 const struct vrend_format_table *src_entry, 393 const struct vrend_format_table *dst_entry) 394 { 395 assert(pipe_tex_target < PIPE_MAX_TEXTURE_TYPES); 396 397 bool needs_swizzle = dst_entry->flags & VIRGL_BIND_NEED_SWIZZLE; 398 399 if (needs_swizzle || nr_samples > 1) { 400 const uint8_t *swizzle = needs_swizzle ? dst_entry->swizzle : NULL; 401 GLuint *shader = &blit_ctx->fs_texfetch_col_swizzle; 402 if (shader) { 403 glDeleteShader(*shader); 404 } 405 406 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, nr_samples); 407 enum tgsi_return_type tgsi_ret = tgsi_ret_for_format(src_entry->format); 408 409 if (nr_samples > 1) { 410 // Integer textures are resolved using just one sample 411 int msaa_samples = tgsi_ret == TGSI_RETURN_TYPE_UNORM ? nr_samples : 1; 412 *shader = blit_build_frag_tex_col_msaa(blit_ctx, tgsi_tex, tgsi_ret, 413 swizzle, msaa_samples); 414 } else { 415 *shader = blit_build_frag_tex_col(blit_ctx, tgsi_tex, tgsi_ret, swizzle); 416 } 417 418 return *shader; 419 } else { 420 GLuint *shader = &blit_ctx->fs_texfetch_col[pipe_tex_target]; 421 422 if (!*shader) { 423 unsigned tgsi_tex = util_pipe_tex_to_tgsi_tex(pipe_tex_target, 0); 424 enum tgsi_return_type tgsi_ret = tgsi_ret_for_format(src_entry->format); 425 426 *shader = blit_build_frag_tex_col(blit_ctx, tgsi_tex, tgsi_ret, NULL); 427 } 428 return *shader; 429 } 430 } 431 432 static void vrend_renderer_init_blit_ctx(struct vrend_blitter_ctx *blit_ctx) 433 { 434 struct virgl_gl_ctx_param ctx_params; 435 int i; 436 if (blit_ctx->initialised) { 437 vrend_clicbs->make_current(0, blit_ctx->gl_context); 438 return; 439 } 440 441 blit_ctx->initialised = true; 442 blit_ctx->use_gles = epoxy_is_desktop_gl() == 0; 443 ctx_params.shared = true; 444 for (uint32_t i = 0; i < ARRAY_SIZE(gl_versions); i++) { 445 ctx_params.major_ver = gl_versions[i].major; 446 ctx_params.minor_ver = gl_versions[i].minor; 447 448 blit_ctx->gl_context = vrend_clicbs->create_gl_context(0, &ctx_params); 449 if (blit_ctx->gl_context) 450 break; 451 } 452 453 vrend_clicbs->make_current(0, blit_ctx->gl_context); 454 glGenVertexArrays(1, &blit_ctx->vaoid); 455 glGenFramebuffers(1, &blit_ctx->fb_id); 456 457 glGenBuffers(1, &blit_ctx->vbo_id); 458 blit_build_vs_passthrough(blit_ctx); 459 460 for (i = 0; i < 4; i++) 461 blit_ctx->vertices[i][0][3] = 1; /*v.w*/ 462 glBindVertexArray(blit_ctx->vaoid); 463 glBindBuffer(GL_ARRAY_BUFFER, blit_ctx->vbo_id); 464 465 if (!blit_ctx->use_gles) 466 glEnable(GL_FRAMEBUFFER_SRGB); 467 blit_ctx->framebuffer_srgb_enabled = true; 468 } 469 470 static inline GLenum convert_mag_filter(unsigned int filter) 471 { 472 if (filter == PIPE_TEX_FILTER_NEAREST) 473 return GL_NEAREST; 474 return GL_LINEAR; 475 } 476 477 static void blitter_set_dst_dim(struct vrend_blitter_ctx *blit_ctx, 478 unsigned width, unsigned height) 479 { 480 blit_ctx->dst_width = width; 481 blit_ctx->dst_height = height; 482 } 483 484 static void blitter_set_rectangle(struct vrend_blitter_ctx *blit_ctx, 485 int x1, int y1, int x2, int y2, 486 float depth) 487 { 488 int i; 489 490 /* set vertex positions */ 491 blit_ctx->vertices[0][0][0] = (float)x1 / blit_ctx->dst_width * 2.0f - 1.0f; /*v0.x*/ 492 blit_ctx->vertices[0][0][1] = (float)y1 / blit_ctx->dst_height * 2.0f - 1.0f; /*v0.y*/ 493 494 blit_ctx->vertices[1][0][0] = (float)x2 / blit_ctx->dst_width * 2.0f - 1.0f; /*v1.x*/ 495 blit_ctx->vertices[1][0][1] = (float)y1 / blit_ctx->dst_height * 2.0f - 1.0f; /*v1.y*/ 496 497 blit_ctx->vertices[2][0][0] = (float)x2 / blit_ctx->dst_width * 2.0f - 1.0f; /*v2.x*/ 498 blit_ctx->vertices[2][0][1] = (float)y2 / blit_ctx->dst_height * 2.0f - 1.0f; /*v2.y*/ 499 500 blit_ctx->vertices[3][0][0] = (float)x1 / blit_ctx->dst_width * 2.0f - 1.0f; /*v3.x*/ 501 blit_ctx->vertices[3][0][1] = (float)y2 / blit_ctx->dst_height * 2.0f - 1.0f; /*v3.y*/ 502 503 for (i = 0; i < 4; i++) 504 blit_ctx->vertices[i][0][2] = depth; /*z*/ 505 506 glViewport(0, 0, blit_ctx->dst_width, blit_ctx->dst_height); 507 } 508 509 static void get_texcoords(struct vrend_resource *src_res, 510 int src_level, 511 int x1, int y1, int x2, int y2, 512 float out[4]) 513 { 514 bool normalized = src_res->base.target != PIPE_TEXTURE_RECT && 515 src_res->base.nr_samples <= 1; 516 517 if (normalized) { 518 out[0] = x1 / (float)u_minify(src_res->base.width0, src_level); 519 out[1] = y1 / (float)u_minify(src_res->base.height0, src_level); 520 out[2] = x2 / (float)u_minify(src_res->base.width0, src_level); 521 out[3] = y2 / (float)u_minify(src_res->base.height0, src_level); 522 } else { 523 out[0] = (float) x1; 524 out[1] = (float) y1; 525 out[2] = (float) x2; 526 out[3] = (float) y2; 527 } 528 } 529 static void set_texcoords_in_vertices(const float coord[4], 530 float *out, unsigned stride) 531 { 532 out[0] = coord[0]; /*t0.s*/ 533 out[1] = coord[1]; /*t0.t*/ 534 out += stride; 535 out[0] = coord[2]; /*t1.s*/ 536 out[1] = coord[1]; /*t1.t*/ 537 out += stride; 538 out[0] = coord[2]; /*t2.s*/ 539 out[1] = coord[3]; /*t2.t*/ 540 out += stride; 541 out[0] = coord[0]; /*t3.s*/ 542 out[1] = coord[3]; /*t3.t*/ 543 } 544 545 static void blitter_set_texcoords(struct vrend_blitter_ctx *blit_ctx, 546 struct vrend_resource *src_res, 547 int level, 548 float layer, unsigned sample, 549 int x1, int y1, int x2, int y2) 550 { 551 float coord[4]; 552 float face_coord[4][2]; 553 int i; 554 get_texcoords(src_res, level, x1, y1, x2, y2, coord); 555 556 if (src_res->base.target == PIPE_TEXTURE_CUBE || 557 src_res->base.target == PIPE_TEXTURE_CUBE_ARRAY) { 558 set_texcoords_in_vertices(coord, &face_coord[0][0], 2); 559 util_map_texcoords2d_onto_cubemap((unsigned)layer % 6, 560 /* pointer, stride in floats */ 561 &face_coord[0][0], 2, 562 &blit_ctx->vertices[0][1][0], 8, 563 FALSE); 564 } else { 565 set_texcoords_in_vertices(coord, &blit_ctx->vertices[0][1][0], 8); 566 } 567 568 switch (src_res->base.target) { 569 case PIPE_TEXTURE_3D: 570 { 571 float r = layer / (float)u_minify(src_res->base.depth0, 572 level); 573 for (i = 0; i < 4; i++) 574 blit_ctx->vertices[i][1][2] = r; /*r*/ 575 } 576 break; 577 578 case PIPE_TEXTURE_1D_ARRAY: 579 for (i = 0; i < 4; i++) 580 blit_ctx->vertices[i][1][1] = (float) layer; /*t*/ 581 break; 582 583 case PIPE_TEXTURE_2D_ARRAY: 584 for (i = 0; i < 4; i++) { 585 blit_ctx->vertices[i][1][2] = (float) layer; /*r*/ 586 blit_ctx->vertices[i][1][3] = (float) sample; /*q*/ 587 } 588 break; 589 case PIPE_TEXTURE_CUBE_ARRAY: 590 for (i = 0; i < 4; i++) 591 blit_ctx->vertices[i][1][3] = (float) ((unsigned)layer / 6); /*w*/ 592 break; 593 case PIPE_TEXTURE_2D: 594 for (i = 0; i < 4; i++) { 595 blit_ctx->vertices[i][1][3] = (float) sample; /*r*/ 596 } 597 break; 598 default:; 599 } 600 } 601 #if 0 602 static void set_dsa_keep_depth_stencil(void) 603 { 604 glDisable(GL_STENCIL_TEST); 605 glDisable(GL_DEPTH_TEST); 606 glDepthMask(GL_FALSE); 607 } 608 #endif 609 610 static void set_dsa_write_depth_keep_stencil(void) 611 { 612 glDisable(GL_STENCIL_TEST); 613 glEnable(GL_DEPTH_TEST); 614 glDepthFunc(GL_ALWAYS); 615 glDepthMask(GL_TRUE); 616 } 617 618 static inline GLenum to_gl_swizzle(int swizzle) 619 { 620 switch (swizzle) { 621 case PIPE_SWIZZLE_RED: return GL_RED; 622 case PIPE_SWIZZLE_GREEN: return GL_GREEN; 623 case PIPE_SWIZZLE_BLUE: return GL_BLUE; 624 case PIPE_SWIZZLE_ALPHA: return GL_ALPHA; 625 case PIPE_SWIZZLE_ZERO: return GL_ZERO; 626 case PIPE_SWIZZLE_ONE: return GL_ONE; 627 default: 628 assert(0); 629 return 0; 630 } 631 } 632 633 /* Calculate the delta required to keep 'v' within [0, max] */ 634 static int calc_delta_for_bound(int v, int max) 635 { 636 int delta = 0; 637 638 if (v < 0) 639 delta = -v; 640 else if (v > max) 641 delta = - (v - max); 642 643 return delta; 644 } 645 646 /* Calculate the deltas for the source blit region points in order to bound 647 * them within the source resource extents */ 648 static void calc_src_deltas_for_bounds(struct vrend_resource *src_res, 649 const struct pipe_blit_info *info, 650 struct vrend_blitter_delta *src0_delta, 651 struct vrend_blitter_delta *src1_delta) 652 { 653 int max_x = u_minify(src_res->base.width0, info->src.level) - 1; 654 int max_y = u_minify(src_res->base.height0, info->src.level) - 1; 655 656 /* Whether the bounds for the coordinates of a point are inclusive or 657 * exclusive depends on the direction of the blit read. Adjust the max 658 * bounds accordingly, with an adjustment of 0 for inclusive, and 1 for 659 * exclusive. */ 660 int src0_x_excl = info->src.box.width < 0; 661 int src0_y_excl = info->src.box.height < 0; 662 663 src0_delta->dx = calc_delta_for_bound(info->src.box.x, max_x + src0_x_excl); 664 src0_delta->dy = calc_delta_for_bound(info->src.box.y, max_y + src0_y_excl); 665 666 src1_delta->dx = calc_delta_for_bound(info->src.box.x + info->src.box.width, 667 max_x + !src0_x_excl); 668 src1_delta->dy = calc_delta_for_bound(info->src.box.y + info->src.box.height, 669 max_y + !src0_y_excl); 670 } 671 672 /* Calculate dst delta values to adjust the dst points for any changes in the 673 * src points */ 674 static void calc_dst_deltas_from_src(const struct pipe_blit_info *info, 675 const struct vrend_blitter_delta *src0_delta, 676 const struct vrend_blitter_delta *src1_delta, 677 struct vrend_blitter_delta *dst0_delta, 678 struct vrend_blitter_delta *dst1_delta) 679 { 680 float scale_x = (float)info->dst.box.width / (float)info->src.box.width; 681 float scale_y = (float)info->dst.box.height / (float)info->src.box.height; 682 683 dst0_delta->dx = src0_delta->dx * scale_x; 684 dst0_delta->dy = src0_delta->dy * scale_y; 685 686 dst1_delta->dx = src1_delta->dx * scale_x; 687 dst1_delta->dy = src1_delta->dy * scale_y; 688 } 689 690 /* implement blitting using OpenGL. */ 691 void vrend_renderer_blit_gl(UNUSED struct vrend_context *ctx, 692 struct vrend_resource *src_res, 693 struct vrend_resource *dst_res, 694 const struct pipe_blit_info *info, 695 bool has_texture_srgb_decode) 696 { 697 struct vrend_blitter_ctx *blit_ctx = &vrend_blit_ctx; 698 GLuint buffers; 699 GLuint prog_id; 700 GLuint fs_id; 701 GLint lret; 702 GLenum filter; 703 GLuint pos_loc, tc_loc; 704 GLuint samp_loc; 705 bool has_depth, has_stencil; 706 bool blit_stencil, blit_depth; 707 int dst_z; 708 struct vrend_blitter_delta src0_delta, src1_delta, dst0_delta, dst1_delta; 709 struct vrend_blitter_point src0, src1, dst0, dst1; 710 const struct util_format_description *src_desc = 711 util_format_description(src_res->base.format); 712 const struct util_format_description *dst_desc = 713 util_format_description(dst_res->base.format); 714 const struct vrend_format_table *src_entry = 715 vrend_get_format_table_entry(info->src.format); 716 const struct vrend_format_table *dst_entry = 717 vrend_get_format_table_entry(info->dst.format); 718 719 has_depth = util_format_has_depth(src_desc) && 720 util_format_has_depth(dst_desc); 721 has_stencil = util_format_has_stencil(src_desc) && 722 util_format_has_stencil(dst_desc); 723 724 blit_depth = has_depth && (info->mask & PIPE_MASK_Z); 725 blit_stencil = has_stencil && (info->mask & PIPE_MASK_S) & 0; 726 727 filter = convert_mag_filter(info->filter); 728 vrend_renderer_init_blit_ctx(blit_ctx); 729 730 blitter_set_dst_dim(blit_ctx, 731 u_minify(dst_res->base.width0, info->dst.level), 732 u_minify(dst_res->base.height0, info->dst.level)); 733 734 /* Calculate src and dst points taking deltas into account */ 735 calc_src_deltas_for_bounds(src_res, info, &src0_delta, &src1_delta); 736 calc_dst_deltas_from_src(info, &src0_delta, &src1_delta, &dst0_delta, &dst1_delta); 737 738 src0.x = info->src.box.x + src0_delta.dx; 739 src0.y = info->src.box.y + src0_delta.dy; 740 src1.x = info->src.box.x + info->src.box.width + src1_delta.dx; 741 src1.y = info->src.box.y + info->src.box.height + src1_delta.dy; 742 743 dst0.x = info->dst.box.x + dst0_delta.dx; 744 dst0.y = info->dst.box.y + dst0_delta.dy; 745 dst1.x = info->dst.box.x + info->dst.box.width + dst1_delta.dx; 746 dst1.y = info->dst.box.y + info->dst.box.height + dst1_delta.dy; 747 748 blitter_set_rectangle(blit_ctx, dst0.x, dst0.y, dst1.x, dst1.y, 0); 749 750 prog_id = glCreateProgram(); 751 glAttachShader(prog_id, blit_ctx->vs); 752 753 if (blit_depth || blit_stencil) { 754 fs_id = blit_get_frag_tex_writedepth(blit_ctx, src_res->base.target, 755 src_res->base.nr_samples); 756 } else { 757 fs_id = blit_get_frag_tex_col(blit_ctx, src_res->base.target, 758 src_res->base.nr_samples, 759 src_entry, dst_entry); 760 } 761 glAttachShader(prog_id, fs_id); 762 763 glLinkProgram(prog_id); 764 glGetProgramiv(prog_id, GL_LINK_STATUS, &lret); 765 if (lret == GL_FALSE) { 766 char infolog[65536]; 767 int len; 768 glGetProgramInfoLog(prog_id, 65536, &len, infolog); 769 fprintf(stderr,"got error linking\n%s\n", infolog); 770 /* dump shaders */ 771 glDeleteProgram(prog_id); 772 return; 773 } 774 775 glUseProgram(prog_id); 776 777 glBindFramebuffer(GL_FRAMEBUFFER_EXT, blit_ctx->fb_id); 778 vrend_fb_bind_texture(dst_res, 0, info->dst.level, info->dst.box.z); 779 780 buffers = GL_COLOR_ATTACHMENT0_EXT; 781 glDrawBuffers(1, &buffers); 782 783 glBindTexture(src_res->target, src_res->id); 784 785 if (src_entry->flags & VIRGL_BIND_NEED_SWIZZLE) { 786 glTexParameteri(src_res->target, GL_TEXTURE_SWIZZLE_R, 787 to_gl_swizzle(src_entry->swizzle[0])); 788 glTexParameteri(src_res->target, GL_TEXTURE_SWIZZLE_G, 789 to_gl_swizzle(src_entry->swizzle[1])); 790 glTexParameteri(src_res->target, GL_TEXTURE_SWIZZLE_B, 791 to_gl_swizzle(src_entry->swizzle[2])); 792 glTexParameteri(src_res->target, GL_TEXTURE_SWIZZLE_A, 793 to_gl_swizzle(src_entry->swizzle[3])); 794 } 795 796 /* Just make sure that no stale state disabled decoding */ 797 if (has_texture_srgb_decode && util_format_is_srgb(src_res->base.format)) 798 glTexParameteri(src_res->target, GL_TEXTURE_SRGB_DECODE_EXT, GL_DECODE_EXT); 799 800 glTexParameteri(src_res->target, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); 801 glTexParameteri(src_res->target, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); 802 glTexParameteri(src_res->target, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE); 803 804 glTexParameteri(src_res->target, GL_TEXTURE_BASE_LEVEL, info->src.level); 805 glTexParameteri(src_res->target, GL_TEXTURE_MAX_LEVEL, info->src.level); 806 glTexParameterf(src_res->target, GL_TEXTURE_MAG_FILTER, filter); 807 glTexParameterf(src_res->target, GL_TEXTURE_MIN_FILTER, filter); 808 pos_loc = glGetAttribLocation(prog_id, "arg0"); 809 tc_loc = glGetAttribLocation(prog_id, "arg1"); 810 samp_loc = glGetUniformLocation(prog_id, "samp"); 811 812 glUniform1i(samp_loc, 0); 813 814 glVertexAttribPointer(pos_loc, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)0); 815 glVertexAttribPointer(tc_loc, 4, GL_FLOAT, GL_FALSE, 8 * sizeof(float), (void *)(4 * sizeof(float))); 816 817 glEnableVertexAttribArray(pos_loc); 818 glEnableVertexAttribArray(tc_loc); 819 820 set_dsa_write_depth_keep_stencil(); 821 822 for (dst_z = 0; dst_z < info->dst.box.depth; dst_z++) { 823 float dst2src_scale = info->src.box.depth / (float)info->dst.box.depth; 824 float dst_offset = ((info->src.box.depth - 1) - 825 (info->dst.box.depth - 1) * dst2src_scale) * 0.5; 826 float src_z = (dst_z + dst_offset) * dst2src_scale; 827 uint32_t layer = (dst_res->target == GL_TEXTURE_CUBE_MAP) ? info->dst.box.z : dst_z; 828 829 glBindFramebuffer(GL_FRAMEBUFFER_EXT, blit_ctx->fb_id); 830 vrend_fb_bind_texture(dst_res, 0, info->dst.level, layer); 831 832 buffers = GL_COLOR_ATTACHMENT0_EXT; 833 glDrawBuffers(1, &buffers); 834 blitter_set_texcoords(blit_ctx, src_res, info->src.level, 835 info->src.box.z + src_z, 0, 836 src0.x, src0.y, src1.x, src1.y); 837 838 glBufferData(GL_ARRAY_BUFFER, sizeof(blit_ctx->vertices), blit_ctx->vertices, GL_STATIC_DRAW); 839 glDrawArrays(GL_TRIANGLE_FAN, 0, 4); 840 } 841 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_DEPTH_STENCIL_ATTACHMENT, 842 GL_TEXTURE_2D, 0, 0); 843 glFramebufferTexture2DEXT(GL_FRAMEBUFFER_EXT, GL_COLOR_ATTACHMENT0, 844 GL_TEXTURE_2D, 0, 0); 845 }