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