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