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