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