renderer.c revision decf6ed810eae473d043a4a399a5a84f1378a725
1/************************************************************************** 2 * 3 * Copyright 2009 VMware, Inc. All Rights Reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining a 6 * copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sub license, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice (including the 14 * next paragraph) shall be included in all copies or substantial portions 15 * of the Software. 16 * 17 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS 18 * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 19 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. 20 * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR 21 * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, 22 * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE 23 * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 24 * 25 **************************************************************************/ 26 27#include "renderer.h" 28 29#include "vg_context.h" 30 31#include "pipe/p_context.h" 32#include "pipe/p_state.h" 33#include "pipe/p_inlines.h" 34#include "pipe/p_screen.h" 35#include "pipe/p_shader_tokens.h" 36 37#include "util/u_draw_quad.h" 38#include "util/u_simple_shaders.h" 39#include "util/u_memory.h" 40#include "util/u_rect.h" 41 42#include "cso_cache/cso_context.h" 43 44struct renderer { 45 struct pipe_context *pipe; 46 struct vg_context *owner; 47 48 struct cso_context *cso; 49 50 void *fs; 51 52 VGfloat vertices[4][2][4]; 53}; 54 55static void setup_shaders(struct renderer *ctx) 56{ 57 struct pipe_context *pipe = ctx->pipe; 58 /* fragment shader */ 59 ctx->fs = util_make_fragment_tex_shader(pipe); 60} 61 62static struct pipe_buffer * 63setup_vertex_data(struct renderer *ctx, 64 float x0, float y0, float x1, float y1, float z) 65{ 66 ctx->vertices[0][0][0] = x0; 67 ctx->vertices[0][0][1] = y0; 68 ctx->vertices[0][0][2] = z; 69 ctx->vertices[0][1][0] = 0.0f; /*s*/ 70 ctx->vertices[0][1][1] = 0.0f; /*t*/ 71 72 ctx->vertices[1][0][0] = x1; 73 ctx->vertices[1][0][1] = y0; 74 ctx->vertices[1][0][2] = z; 75 ctx->vertices[1][1][0] = 1.0f; /*s*/ 76 ctx->vertices[1][1][1] = 0.0f; /*t*/ 77 78 ctx->vertices[2][0][0] = x1; 79 ctx->vertices[2][0][1] = y1; 80 ctx->vertices[2][0][2] = z; 81 ctx->vertices[2][1][0] = 1.0f; 82 ctx->vertices[2][1][1] = 1.0f; 83 84 ctx->vertices[3][0][0] = x0; 85 ctx->vertices[3][0][1] = y1; 86 ctx->vertices[3][0][2] = z; 87 ctx->vertices[3][1][0] = 0.0f; 88 ctx->vertices[3][1][1] = 1.0f; 89 90 return pipe_user_buffer_create( ctx->pipe->screen, 91 ctx->vertices, 92 sizeof(ctx->vertices) ); 93} 94 95static struct pipe_buffer * 96setup_vertex_data_tex(struct renderer *ctx, 97 float x0, float y0, float x1, float y1, 98 float s0, float t0, float s1, float t1, 99 float z) 100{ 101 ctx->vertices[0][0][0] = x0; 102 ctx->vertices[0][0][1] = y0; 103 ctx->vertices[0][0][2] = z; 104 ctx->vertices[0][1][0] = s0; /*s*/ 105 ctx->vertices[0][1][1] = t0; /*t*/ 106 107 ctx->vertices[1][0][0] = x1; 108 ctx->vertices[1][0][1] = y0; 109 ctx->vertices[1][0][2] = z; 110 ctx->vertices[1][1][0] = s1; /*s*/ 111 ctx->vertices[1][1][1] = t0; /*t*/ 112 113 ctx->vertices[2][0][0] = x1; 114 ctx->vertices[2][0][1] = y1; 115 ctx->vertices[2][0][2] = z; 116 ctx->vertices[2][1][0] = s1; 117 ctx->vertices[2][1][1] = t1; 118 119 ctx->vertices[3][0][0] = x0; 120 ctx->vertices[3][0][1] = y1; 121 ctx->vertices[3][0][2] = z; 122 ctx->vertices[3][1][0] = s0; 123 ctx->vertices[3][1][1] = t1; 124 125 return pipe_user_buffer_create( ctx->pipe->screen, 126 ctx->vertices, 127 sizeof(ctx->vertices) ); 128} 129 130 131static struct pipe_buffer * 132setup_vertex_data_qtex(struct renderer *ctx, 133 float x0, float y0, float x1, float y1, 134 float x2, float y2, float x3, float y3, 135 float s0, float t0, float s1, float t1, 136 float z) 137{ 138 ctx->vertices[0][0][0] = x0; 139 ctx->vertices[0][0][1] = y0; 140 ctx->vertices[0][0][2] = z; 141 ctx->vertices[0][1][0] = s0; /*s*/ 142 ctx->vertices[0][1][1] = t0; /*t*/ 143 144 ctx->vertices[1][0][0] = x1; 145 ctx->vertices[1][0][1] = y1; 146 ctx->vertices[1][0][2] = z; 147 ctx->vertices[1][1][0] = s1; /*s*/ 148 ctx->vertices[1][1][1] = t0; /*t*/ 149 150 ctx->vertices[2][0][0] = x2; 151 ctx->vertices[2][0][1] = y2; 152 ctx->vertices[2][0][2] = z; 153 ctx->vertices[2][1][0] = s1; 154 ctx->vertices[2][1][1] = t1; 155 156 ctx->vertices[3][0][0] = x3; 157 ctx->vertices[3][0][1] = y3; 158 ctx->vertices[3][0][2] = z; 159 ctx->vertices[3][1][0] = s0; 160 ctx->vertices[3][1][1] = t1; 161 162 return pipe_user_buffer_create( ctx->pipe->screen, 163 ctx->vertices, 164 sizeof(ctx->vertices) ); 165} 166 167struct renderer * renderer_create(struct vg_context *owner) 168{ 169 VGint i; 170 struct renderer *renderer = CALLOC_STRUCT(renderer); 171 172 if (!renderer) 173 return NULL; 174 175 renderer->owner = owner; 176 renderer->pipe = owner->pipe; 177 renderer->cso = owner->cso_context; 178 179 setup_shaders(renderer); 180 181 /* init vertex data that doesn't change */ 182 for (i = 0; i < 4; i++) { 183 renderer->vertices[i][0][3] = 1.0f; /* w */ 184 renderer->vertices[i][1][2] = 0.0f; /* r */ 185 renderer->vertices[i][1][3] = 1.0f; /* q */ 186 } 187 188 return renderer; 189} 190 191void renderer_destroy(struct renderer *ctx) 192{ 193#if 0 194 if (ctx->fs) { 195 cso_delete_fragment_shader(ctx->cso, ctx->fs); 196 ctx->fs = NULL; 197 } 198#endif 199 free(ctx); 200} 201 202void renderer_draw_quad(struct renderer *r, 203 VGfloat x1, VGfloat y1, 204 VGfloat x2, VGfloat y2, 205 VGfloat depth) 206{ 207 struct pipe_buffer *buf; 208 209 buf = setup_vertex_data(r, x1, y1, x2, y2, depth); 210 211 if (buf) { 212 util_draw_vertex_buffer(r->pipe, buf, 0, 213 PIPE_PRIM_TRIANGLE_FAN, 214 4, /* verts */ 215 2); /* attribs/vert */ 216 217 pipe_buffer_reference( &buf, 218 NULL ); 219 } 220} 221 222void renderer_draw_texture(struct renderer *r, 223 struct pipe_texture *tex, 224 VGfloat x1offset, VGfloat y1offset, 225 VGfloat x2offset, VGfloat y2offset, 226 VGfloat x1, VGfloat y1, 227 VGfloat x2, VGfloat y2) 228{ 229 struct pipe_context *pipe = r->pipe; 230 struct pipe_buffer *buf; 231 VGfloat s0, t0, s1, t1; 232 233 assert(tex->width0 != 0); 234 assert(tex->height0 != 0); 235 236 s0 = x1offset / tex->width0; 237 s1 = x2offset / tex->width0; 238 t0 = y1offset / tex->height0; 239 t1 = y2offset / tex->height0; 240 241 cso_save_vertex_shader(r->cso); 242 /* shaders */ 243 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner)); 244 245 /* draw quad */ 246 buf = setup_vertex_data_tex(r, x1, y1, x2, y2, 247 s0, t0, s1, t1, 0.0f); 248 249 if (buf) { 250 util_draw_vertex_buffer(pipe, buf, 0, 251 PIPE_PRIM_TRIANGLE_FAN, 252 4, /* verts */ 253 2); /* attribs/vert */ 254 255 pipe_buffer_reference( &buf, 256 NULL ); 257 } 258 259 cso_restore_vertex_shader(r->cso); 260} 261 262void renderer_copy_texture(struct renderer *ctx, 263 struct pipe_texture *src, 264 VGfloat sx1, VGfloat sy1, 265 VGfloat sx2, VGfloat sy2, 266 struct pipe_texture *dst, 267 VGfloat dx1, VGfloat dy1, 268 VGfloat dx2, VGfloat dy2) 269{ 270 struct pipe_context *pipe = ctx->pipe; 271 struct pipe_screen *screen = pipe->screen; 272 struct pipe_buffer *buf; 273 struct pipe_surface *dst_surf = screen->get_tex_surface( 274 screen, dst, 0, 0, 0, 275 PIPE_BUFFER_USAGE_GPU_WRITE); 276 struct pipe_framebuffer_state fb; 277 float s0, t0, s1, t1; 278 279 assert(src->width0 != 0); 280 assert(src->height0 != 0); 281 assert(dst->width0 != 0); 282 assert(dst->height0 != 0); 283 284#if 0 285 debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n", 286 sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2); 287#endif 288 289#if 1 290 s0 = sx1 / src->width0; 291 s1 = sx2 / src->width0; 292 t0 = sy1 / src->height0; 293 t1 = sy2 / src->height0; 294#else 295 s0 = 0; 296 s1 = 1; 297 t0 = 0; 298 t1 = 1; 299#endif 300 301 assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D, 302 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); 303 304 /* save state (restored below) */ 305 cso_save_blend(ctx->cso); 306 cso_save_samplers(ctx->cso); 307 cso_save_sampler_textures(ctx->cso); 308 cso_save_framebuffer(ctx->cso); 309 cso_save_fragment_shader(ctx->cso); 310 cso_save_vertex_shader(ctx->cso); 311 312 cso_save_viewport(ctx->cso); 313 314 315 /* set misc state we care about */ 316 { 317 struct pipe_blend_state blend; 318 memset(&blend, 0, sizeof(blend)); 319 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; 320 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; 321 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 322 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 323 blend.colormask = PIPE_MASK_RGBA; 324 cso_set_blend(ctx->cso, &blend); 325 } 326 327 /* sampler */ 328 { 329 struct pipe_sampler_state sampler; 330 memset(&sampler, 0, sizeof(sampler)); 331 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 332 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 333 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 334 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 335 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 336 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 337 sampler.normalized_coords = 1; 338 cso_single_sampler(ctx->cso, 0, &sampler); 339 cso_single_sampler_done(ctx->cso); 340 } 341 342 vg_set_viewport(ctx->owner, VEGA_Y0_TOP); 343 344 /* texture */ 345 cso_set_sampler_textures(ctx->cso, 1, &src); 346 347 /* shaders */ 348 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); 349 cso_set_fragment_shader_handle(ctx->cso, ctx->fs); 350 351 /* drawing dest */ 352 memset(&fb, 0, sizeof(fb)); 353 fb.width = dst_surf->width; 354 fb.height = dst_surf->height; 355 fb.nr_cbufs = 1; 356 fb.cbufs[0] = dst_surf; 357 { 358 VGint i; 359 for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i) 360 fb.cbufs[i] = 0; 361 } 362 cso_set_framebuffer(ctx->cso, &fb); 363 364 /* draw quad */ 365 buf = setup_vertex_data_tex(ctx, 366 dx1, dy1, 367 dx2, dy2, 368 s0, t0, s1, t1, 369 0.0f); 370 371 if (buf) { 372 util_draw_vertex_buffer(ctx->pipe, buf, 0, 373 PIPE_PRIM_TRIANGLE_FAN, 374 4, /* verts */ 375 2); /* attribs/vert */ 376 377 pipe_buffer_reference( &buf, 378 NULL ); 379 } 380 381 /* restore state we changed */ 382 cso_restore_blend(ctx->cso); 383 cso_restore_samplers(ctx->cso); 384 cso_restore_sampler_textures(ctx->cso); 385 cso_restore_framebuffer(ctx->cso); 386 cso_restore_vertex_shader(ctx->cso); 387 cso_restore_fragment_shader(ctx->cso); 388 cso_restore_viewport(ctx->cso); 389 390 pipe_surface_reference(&dst_surf, NULL); 391} 392 393void renderer_copy_surface(struct renderer *ctx, 394 struct pipe_surface *src, 395 int srcX0, int srcY0, 396 int srcX1, int srcY1, 397 struct pipe_surface *dst, 398 int dstX0, int dstY0, 399 int dstX1, int dstY1, 400 float z, unsigned filter) 401{ 402 struct pipe_context *pipe = ctx->pipe; 403 struct pipe_screen *screen = pipe->screen; 404 struct pipe_buffer *buf; 405 struct pipe_texture texTemp, *tex; 406 struct pipe_surface *texSurf; 407 struct pipe_framebuffer_state fb; 408 struct st_framebuffer *stfb = ctx->owner->draw_buffer; 409 const int srcW = abs(srcX1 - srcX0); 410 const int srcH = abs(srcY1 - srcY0); 411 const int srcLeft = MIN2(srcX0, srcX1); 412 const int srcTop = MIN2(srcY0, srcY1); 413 414 assert(filter == PIPE_TEX_MIPFILTER_NEAREST || 415 filter == PIPE_TEX_MIPFILTER_LINEAR); 416 417 if (srcLeft != srcX0) { 418 /* left-right flip */ 419 int tmp = dstX0; 420 dstX0 = dstX1; 421 dstX1 = tmp; 422 } 423 424 if (srcTop != srcY0) { 425 /* up-down flip */ 426 int tmp = dstY0; 427 dstY0 = dstY1; 428 dstY1 = tmp; 429 } 430 431 assert(screen->is_format_supported(screen, src->format, PIPE_TEXTURE_2D, 432 PIPE_TEXTURE_USAGE_SAMPLER, 0)); 433 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 434 PIPE_TEXTURE_USAGE_SAMPLER, 0)); 435 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 436 PIPE_TEXTURE_USAGE_RENDER_TARGET, 0)); 437 438 /* 439 * XXX for now we're always creating a temporary texture. 440 * Strictly speaking that's not always needed. 441 */ 442 443 /* create temp texture */ 444 memset(&texTemp, 0, sizeof(texTemp)); 445 texTemp.target = PIPE_TEXTURE_2D; 446 texTemp.format = src->format; 447 texTemp.last_level = 0; 448 texTemp.width0 = srcW; 449 texTemp.height0 = srcH; 450 texTemp.depth0 = 1; 451 452 tex = screen->texture_create(screen, &texTemp); 453 if (!tex) 454 return; 455 456 texSurf = screen->get_tex_surface(screen, tex, 0, 0, 0, 457 PIPE_BUFFER_USAGE_GPU_WRITE); 458 459 /* load temp texture */ 460 if (pipe->surface_copy) { 461 pipe->surface_copy(pipe, 462 texSurf, 0, 0, /* dest */ 463 src, srcLeft, srcTop, /* src */ 464 srcW, srcH); /* size */ 465 } else { 466 util_surface_copy(pipe, FALSE, 467 texSurf, 0, 0, /* dest */ 468 src, srcLeft, srcTop, /* src */ 469 srcW, srcH); /* size */ 470 } 471 472 /* free the surface, update the texture if necessary.*/ 473 screen->tex_surface_destroy(texSurf); 474 475 /* save state (restored below) */ 476 cso_save_blend(ctx->cso); 477 cso_save_samplers(ctx->cso); 478 cso_save_sampler_textures(ctx->cso); 479 cso_save_framebuffer(ctx->cso); 480 cso_save_fragment_shader(ctx->cso); 481 cso_save_vertex_shader(ctx->cso); 482 cso_save_viewport(ctx->cso); 483 484 /* set misc state we care about */ 485 { 486 struct pipe_blend_state blend; 487 memset(&blend, 0, sizeof(blend)); 488 blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; 489 blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; 490 blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 491 blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 492 blend.colormask = PIPE_MASK_RGBA; 493 cso_set_blend(ctx->cso, &blend); 494 } 495 496 vg_set_viewport(ctx->owner, VEGA_Y0_TOP); 497 498 /* sampler */ 499 { 500 struct pipe_sampler_state sampler; 501 memset(&sampler, 0, sizeof(sampler)); 502 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 503 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 504 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 505 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 506 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 507 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 508 sampler.normalized_coords = 1; 509 cso_single_sampler(ctx->cso, 0, &sampler); 510 cso_single_sampler_done(ctx->cso); 511 } 512 513 /* texture */ 514 cso_set_sampler_textures(ctx->cso, 1, &tex); 515 516 /* shaders */ 517 cso_set_fragment_shader_handle(ctx->cso, ctx->fs); 518 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); 519 520 /* drawing dest */ 521 if (stfb->strb->surface != dst) { 522 memset(&fb, 0, sizeof(fb)); 523 fb.width = dst->width; 524 fb.height = dst->height; 525 fb.nr_cbufs = 1; 526 fb.cbufs[0] = dst; 527 fb.zsbuf = stfb->dsrb->surface; 528 cso_set_framebuffer(ctx->cso, &fb); 529 } 530 531 /* draw quad */ 532 buf = setup_vertex_data(ctx, 533 (float) dstX0, (float) dstY0, 534 (float) dstX1, (float) dstY1, z); 535 536 if (buf) { 537 util_draw_vertex_buffer(ctx->pipe, buf, 0, 538 PIPE_PRIM_TRIANGLE_FAN, 539 4, /* verts */ 540 2); /* attribs/vert */ 541 542 pipe_buffer_reference( &buf, 543 NULL ); 544 } 545 546 547 /* restore state we changed */ 548 cso_restore_blend(ctx->cso); 549 cso_restore_samplers(ctx->cso); 550 cso_restore_sampler_textures(ctx->cso); 551 cso_restore_framebuffer(ctx->cso); 552 cso_restore_fragment_shader(ctx->cso); 553 cso_restore_vertex_shader(ctx->cso); 554 cso_restore_viewport(ctx->cso); 555 556 pipe_texture_reference(&tex, NULL); 557} 558 559void renderer_texture_quad(struct renderer *r, 560 struct pipe_texture *tex, 561 VGfloat x1offset, VGfloat y1offset, 562 VGfloat x2offset, VGfloat y2offset, 563 VGfloat x1, VGfloat y1, 564 VGfloat x2, VGfloat y2, 565 VGfloat x3, VGfloat y3, 566 VGfloat x4, VGfloat y4) 567{ 568 struct pipe_context *pipe = r->pipe; 569 struct pipe_buffer *buf; 570 VGfloat s0, t0, s1, t1; 571 572 assert(tex->width0 != 0); 573 assert(tex->height0 != 0); 574 575 s0 = x1offset / tex->width0; 576 s1 = x2offset / tex->width0; 577 t0 = y1offset / tex->height0; 578 t1 = y2offset / tex->height0; 579 580 cso_save_vertex_shader(r->cso); 581 /* shaders */ 582 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner)); 583 584 /* draw quad */ 585 buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4, 586 s0, t0, s1, t1, 0.0f); 587 588 if (buf) { 589 util_draw_vertex_buffer(pipe, buf, 0, 590 PIPE_PRIM_TRIANGLE_FAN, 591 4, /* verts */ 592 2); /* attribs/vert */ 593 594 pipe_buffer_reference(&buf, 595 NULL); 596 } 597 598 cso_restore_vertex_shader(r->cso); 599} 600