renderer.c revision c36c3d86b62b525291b1c6527de3ac5de93a2faf
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 0, 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_subresource subsrc, subdst; 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 0, PIPE_BIND_SAMPLER_VIEW, 0)); 445 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 446 0, PIPE_BIND_SAMPLER_VIEW, 0)); 447 assert(screen->is_format_supported(screen, dst->format, PIPE_TEXTURE_2D, 448 0, 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 texTemp.bind = PIPE_BIND_SAMPLER_VIEW; 464 465 tex = screen->resource_create(screen, &texTemp); 466 if (!tex) 467 return; 468 469 u_sampler_view_default_template(&view_templ, tex, tex->format); 470 view = pipe->create_sampler_view(pipe, tex, &view_templ); 471 472 if (!view) 473 return; 474 475 subdst.face = 0; 476 subdst.level = 0; 477 subsrc.face = src->face; 478 subsrc.level = src->level; 479 480 pipe->resource_copy_region(pipe, 481 tex, subdst, 0, 0, 0, /* dest */ 482 src->texture, subsrc, srcLeft, srcTop, src->zslice, /* src */ 483 srcW, srcH); /* size */ 484 485 /* save state (restored below) */ 486 cso_save_blend(ctx->cso); 487 cso_save_samplers(ctx->cso); 488 cso_save_fragment_sampler_views(ctx->cso); 489 cso_save_framebuffer(ctx->cso); 490 cso_save_fragment_shader(ctx->cso); 491 cso_save_vertex_shader(ctx->cso); 492 cso_save_viewport(ctx->cso); 493 494 /* set misc state we care about */ 495 { 496 struct pipe_blend_state blend; 497 memset(&blend, 0, sizeof(blend)); 498 blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 499 blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 500 blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 501 blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 502 blend.rt[0].colormask = PIPE_MASK_RGBA; 503 cso_set_blend(ctx->cso, &blend); 504 } 505 506 vg_set_viewport(ctx->owner, VEGA_Y0_TOP); 507 508 /* sampler */ 509 { 510 struct pipe_sampler_state sampler; 511 memset(&sampler, 0, sizeof(sampler)); 512 sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 513 sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 514 sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 515 sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 516 sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 517 sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 518 sampler.normalized_coords = 1; 519 cso_single_sampler(ctx->cso, 0, &sampler); 520 cso_single_sampler_done(ctx->cso); 521 } 522 523 /* texture */ 524 cso_set_fragment_sampler_views(ctx->cso, 1, &view); 525 526 /* shaders */ 527 cso_set_fragment_shader_handle(ctx->cso, ctx->fs); 528 cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner)); 529 530 /* drawing dest */ 531 if (stfb->strb->surface != dst) { 532 memset(&fb, 0, sizeof(fb)); 533 fb.width = dst->width; 534 fb.height = dst->height; 535 fb.nr_cbufs = 1; 536 fb.cbufs[0] = dst; 537 fb.zsbuf = stfb->dsrb->surface; 538 cso_set_framebuffer(ctx->cso, &fb); 539 } 540 541 /* draw quad */ 542 buf = setup_vertex_data(ctx, 543 (float) dstX0, (float) dstY0, 544 (float) dstX1, (float) dstY1, z); 545 546 if (buf) { 547 cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems); 548 util_draw_vertex_buffer(ctx->pipe, buf, 0, 549 PIPE_PRIM_TRIANGLE_FAN, 550 4, /* verts */ 551 2); /* attribs/vert */ 552 553 pipe_resource_reference( &buf, 554 NULL ); 555 } 556 557 558 /* restore state we changed */ 559 cso_restore_blend(ctx->cso); 560 cso_restore_samplers(ctx->cso); 561 cso_restore_fragment_sampler_views(ctx->cso); 562 cso_restore_framebuffer(ctx->cso); 563 cso_restore_fragment_shader(ctx->cso); 564 cso_restore_vertex_shader(ctx->cso); 565 cso_restore_viewport(ctx->cso); 566 567 pipe_resource_reference(&tex, NULL); 568 pipe_sampler_view_reference(&view, NULL); 569} 570 571void renderer_texture_quad(struct renderer *r, 572 struct pipe_resource *tex, 573 VGfloat x1offset, VGfloat y1offset, 574 VGfloat x2offset, VGfloat y2offset, 575 VGfloat x1, VGfloat y1, 576 VGfloat x2, VGfloat y2, 577 VGfloat x3, VGfloat y3, 578 VGfloat x4, VGfloat y4) 579{ 580 struct pipe_context *pipe = r->pipe; 581 struct pipe_resource *buf; 582 VGfloat s0, t0, s1, t1; 583 584 assert(tex->width0 != 0); 585 assert(tex->height0 != 0); 586 587 s0 = x1offset / tex->width0; 588 s1 = x2offset / tex->width0; 589 t0 = y1offset / tex->height0; 590 t1 = y2offset / tex->height0; 591 592 cso_save_vertex_shader(r->cso); 593 /* shaders */ 594 cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner)); 595 596 /* draw quad */ 597 buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4, 598 s0, t0, s1, t1, 0.0f); 599 600 if (buf) { 601 cso_set_vertex_elements(r->cso, 2, r->owner->velems); 602 util_draw_vertex_buffer(pipe, buf, 0, 603 PIPE_PRIM_TRIANGLE_FAN, 604 4, /* verts */ 605 2); /* attribs/vert */ 606 607 pipe_resource_reference(&buf, 608 NULL); 609 } 610 611 cso_restore_vertex_shader(r->cso); 612} 613