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