vg_context.c revision 910b58039a3980d9857380cf367bdbe2395d791f
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 "vg_context.h" 28 29#include "paint.h" 30#include "renderer.h" 31#include "shaders_cache.h" 32#include "shader.h" 33#include "asm_util.h" 34#include "st_inlines.h" 35 36#include "pipe/p_context.h" 37#include "pipe/p_inlines.h" 38#include "pipe/p_shader_tokens.h" 39 40#include "cso_cache/cso_context.h" 41 42#include "util/u_simple_shaders.h" 43#include "util/u_memory.h" 44#include "util/u_blit.h" 45 46struct vg_context *_vg_context = 0; 47 48struct vg_context * vg_current_context(void) 49{ 50 return _vg_context; 51} 52 53static void init_clear(struct vg_context *st) 54{ 55 struct pipe_context *pipe = st->pipe; 56 57 /* rasterizer state: bypass clipping */ 58 memset(&st->clear.raster, 0, sizeof(st->clear.raster)); 59 st->clear.raster.gl_rasterization_rules = 1; 60 61 /* fragment shader state: color pass-through program */ 62 st->clear.fs = 63 util_make_fragment_passthrough_shader(pipe); 64} 65void vg_set_current_context(struct vg_context *ctx) 66{ 67 _vg_context = ctx; 68} 69 70struct vg_context * vg_create_context(struct pipe_context *pipe, 71 const void *visual, 72 struct vg_context *share) 73{ 74 struct vg_context *ctx; 75 76 ctx = CALLOC_STRUCT(vg_context); 77 78 ctx->pipe = pipe; 79 80 vg_init_state(&ctx->state.vg); 81 ctx->state.dirty = ALL_DIRTY; 82 83 ctx->cso_context = cso_create_context(pipe); 84 85 init_clear(ctx); 86 87 ctx->default_paint = paint_create(ctx); 88 ctx->state.vg.stroke_paint = ctx->default_paint; 89 ctx->state.vg.fill_paint = ctx->default_paint; 90 91 92 ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 93 ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 94 ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 95 ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 96 ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 97 ctx->mask.sampler.normalized_coords = 0; 98 99 ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 100 ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; 101 ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; 102 ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST; 103 ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST; 104 ctx->blend_sampler.normalized_coords = 0; 105 106 vg_set_error(ctx, VG_NO_ERROR); 107 108 ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create(); 109 ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create(); 110 ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create(); 111 ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create(); 112 ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create(); 113 114 ctx->renderer = renderer_create(ctx); 115 ctx->sc = shaders_cache_create(ctx); 116 ctx->shader = shader_create(ctx); 117 118 ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context); 119 120 return ctx; 121} 122 123void vg_destroy_context(struct vg_context *ctx) 124{ 125 struct pipe_constant_buffer *cbuf = &ctx->mask.cbuf; 126 struct pipe_constant_buffer *vsbuf = &ctx->vs_const_buffer; 127 128 util_destroy_blit(ctx->blit); 129 renderer_destroy(ctx->renderer); 130 shaders_cache_destroy(ctx->sc); 131 shader_destroy(ctx->shader); 132 paint_destroy(ctx->default_paint); 133 134 if (cbuf && cbuf->buffer) 135 pipe_buffer_reference(&cbuf->buffer, NULL); 136 137 if (vsbuf && vsbuf->buffer) 138 pipe_buffer_reference(&vsbuf->buffer, NULL); 139 140 if (ctx->clear.fs) { 141 cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs); 142 ctx->clear.fs = NULL; 143 } 144 145 if (ctx->plain_vs) { 146 vg_shader_destroy(ctx, ctx->plain_vs); 147 ctx->plain_vs = NULL; 148 } 149 if (ctx->clear_vs) { 150 vg_shader_destroy(ctx, ctx->clear_vs); 151 ctx->clear_vs = NULL; 152 } 153 if (ctx->texture_vs) { 154 vg_shader_destroy(ctx, ctx->texture_vs); 155 ctx->texture_vs = NULL; 156 } 157 158 if (ctx->pass_through_depth_fs) 159 vg_shader_destroy(ctx, ctx->pass_through_depth_fs); 160 if (ctx->mask.union_fs) 161 vg_shader_destroy(ctx, ctx->mask.union_fs); 162 if (ctx->mask.intersect_fs) 163 vg_shader_destroy(ctx, ctx->mask.intersect_fs); 164 if (ctx->mask.subtract_fs) 165 vg_shader_destroy(ctx, ctx->mask.subtract_fs); 166 if (ctx->mask.set_fs) 167 vg_shader_destroy(ctx, ctx->mask.set_fs); 168 169 cso_release_all(ctx->cso_context); 170 cso_destroy_context(ctx->cso_context); 171 172 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]); 173 cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]); 174 cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]); 175 cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]); 176 cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]); 177 178 free(ctx); 179} 180 181void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type) 182{ 183 obj->type = type; 184 obj->ctx = ctx; 185} 186 187VGboolean vg_context_is_object_valid(struct vg_context *ctx, 188 enum vg_object_type type, 189 void *ptr) 190{ 191 if (ctx) { 192 struct cso_hash *hash = ctx->owned_objects[type]; 193 if (!hash) 194 return VG_FALSE; 195 return cso_hash_contains(hash, (unsigned)(long)ptr); 196 } 197 return VG_FALSE; 198} 199 200void vg_context_add_object(struct vg_context *ctx, 201 enum vg_object_type type, 202 void *ptr) 203{ 204 if (ctx) { 205 struct cso_hash *hash = ctx->owned_objects[type]; 206 if (!hash) 207 return; 208 cso_hash_insert(hash, (unsigned)(long)ptr, ptr); 209 } 210} 211 212void vg_context_remove_object(struct vg_context *ctx, 213 enum vg_object_type type, 214 void *ptr) 215{ 216 if (ctx) { 217 struct cso_hash *hash = ctx->owned_objects[type]; 218 if (!hash) 219 return; 220 cso_hash_take(hash, (unsigned)(long)ptr); 221 } 222} 223 224static void update_clip_state(struct vg_context *ctx) 225{ 226 struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa; 227 struct vg_state *state = &ctx->state.vg; 228 229 memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state)); 230 231 if (state->scissoring) { 232 struct pipe_blend_state *blend = &ctx->state.g3d.blend; 233 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 234 int i; 235 236 dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/ 237 dsa->depth.func = PIPE_FUNC_ALWAYS; 238 dsa->depth.enabled = 1; 239 240 cso_save_blend(ctx->cso_context); 241 cso_save_fragment_shader(ctx->cso_context); 242 /* set a passthrough shader */ 243 if (!ctx->pass_through_depth_fs) 244 ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe, 245 pass_through_depth_asm, 246 40, 247 PIPE_SHADER_FRAGMENT); 248 cso_set_fragment_shader_handle(ctx->cso_context, 249 ctx->pass_through_depth_fs->driver); 250 cso_set_depth_stencil_alpha(ctx->cso_context, dsa); 251 252 ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0); 253 254 /* disable color writes */ 255 blend->colormask = 0; /*disable colorwrites*/ 256 cso_set_blend(ctx->cso_context, blend); 257 258 /* enable scissoring */ 259 for (i = 0; i < state->scissor_rects_num; ++i) { 260 const float x = state->scissor_rects[i * 4 + 0].f; 261 const float y = state->scissor_rects[i * 4 + 1].f; 262 const float width = state->scissor_rects[i * 4 + 2].f; 263 const float height = state->scissor_rects[i * 4 + 3].f; 264 VGfloat minx, miny, maxx, maxy; 265 266 minx = 0; 267 miny = 0; 268 maxx = fb->width; 269 maxy = fb->height; 270 271 if (x > minx) 272 minx = x; 273 if (y > miny) 274 miny = y; 275 276 if (x + width < maxx) 277 maxx = x + width; 278 if (y + height < maxy) 279 maxy = y + height; 280 281 /* check for null space */ 282 if (minx >= maxx || miny >= maxy) 283 minx = miny = maxx = maxy = 0; 284 285 /*glClear(GL_DEPTH_BUFFER_BIT);*/ 286 renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f); 287 } 288 289 blend->colormask = 1; /*enable colorwrites*/ 290 cso_restore_blend(ctx->cso_context); 291 cso_restore_fragment_shader(ctx->cso_context); 292 293 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */ 294 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/ 295 dsa->depth.func = PIPE_FUNC_GEQUAL; 296 } 297} 298 299void vg_validate_state(struct vg_context *ctx) 300{ 301 if ((ctx->state.dirty & BLEND_DIRTY)) { 302 struct pipe_blend_state *blend = &ctx->state.g3d.blend; 303 memset(blend, 0, sizeof(struct pipe_blend_state)); 304 blend->blend_enable = 1; 305 blend->colormask |= PIPE_MASK_R; 306 blend->colormask |= PIPE_MASK_G; 307 blend->colormask |= PIPE_MASK_B; 308 blend->colormask |= PIPE_MASK_A; 309 310 switch (ctx->state.vg.blend_mode) { 311 case VG_BLEND_SRC: 312 blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; 313 blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; 314 blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 315 blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 316 break; 317 case VG_BLEND_SRC_OVER: 318 blend->rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 319 blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; 320 blend->rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 321 blend->alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 322 break; 323 case VG_BLEND_DST_OVER: 324 blend->rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; 325 blend->alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; 326 blend->rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; 327 blend->alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; 328 break; 329 case VG_BLEND_SRC_IN: 330 blend->rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; 331 blend->alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; 332 blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 333 blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 334 break; 335 case VG_BLEND_DST_IN: 336 blend->rgb_src_factor = PIPE_BLENDFACTOR_ZERO; 337 blend->alpha_src_factor = PIPE_BLENDFACTOR_ZERO; 338 blend->rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 339 blend->alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 340 break; 341 case VG_BLEND_MULTIPLY: 342 case VG_BLEND_SCREEN: 343 case VG_BLEND_DARKEN: 344 case VG_BLEND_LIGHTEN: 345 blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; 346 blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; 347 blend->rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 348 blend->alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 349 break; 350 case VG_BLEND_ADDITIVE: 351 blend->rgb_src_factor = PIPE_BLENDFACTOR_ONE; 352 blend->alpha_src_factor = PIPE_BLENDFACTOR_ONE; 353 blend->rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 354 blend->alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 355 break; 356 default: 357 assert(!"not implemented blend mode"); 358 } 359 cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend); 360 } 361 if ((ctx->state.dirty & RASTERIZER_DIRTY)) { 362 struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer; 363 memset(raster, 0, sizeof(struct pipe_rasterizer_state)); 364 raster->gl_rasterization_rules = 1; 365 cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer); 366 } 367 if ((ctx->state.dirty & VIEWPORT_DIRTY)) { 368 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 369 const VGint param_bytes = 8 * sizeof(VGfloat); 370 VGfloat vs_consts[8] = { 371 2.f/fb->width, 2.f/fb->height, 1, 1, 372 -1, -1, 0, 0 373 }; 374 struct pipe_constant_buffer *cbuf = &ctx->vs_const_buffer; 375 376 vg_set_viewport(ctx, VEGA_Y0_BOTTOM); 377 378 pipe_buffer_reference(&cbuf->buffer, NULL); 379 cbuf->buffer = pipe_buffer_create(ctx->pipe->screen, 16, 380 PIPE_BUFFER_USAGE_CONSTANT, 381 param_bytes); 382 383 if (cbuf->buffer) { 384 st_no_flush_pipe_buffer_write(ctx, cbuf->buffer, 385 0, param_bytes, vs_consts); 386 } 387 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, cbuf); 388 } 389 if ((ctx->state.dirty & VS_DIRTY)) { 390 cso_set_vertex_shader_handle(ctx->cso_context, 391 vg_plain_vs(ctx)); 392 } 393 394 /* must be last because it renders to the depth buffer*/ 395 if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) { 396 update_clip_state(ctx); 397 cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa); 398 } 399 400 shader_set_masking(ctx->shader, ctx->state.vg.masking); 401 shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode); 402 403 ctx->state.dirty = NONE_DIRTY; 404} 405 406VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type) 407{ 408 struct vg_object *obj = ptr; 409 if (ptr && is_aligned(obj) && obj->type == type) 410 return VG_TRUE; 411 else 412 return VG_FALSE; 413} 414 415void vg_set_error(struct vg_context *ctx, 416 VGErrorCode code) 417{ 418 /*vgGetError returns the oldest error code provided by 419 * an API call on the current context since the previous 420 * call to vgGetError on that context (or since the creation 421 of the context).*/ 422 if (ctx->_error == VG_NO_ERROR) 423 ctx->_error = code; 424} 425 426void vg_prepare_blend_surface(struct vg_context *ctx) 427{ 428 struct pipe_surface *dest_surface = NULL; 429 struct pipe_context *pipe = ctx->pipe; 430 struct st_framebuffer *stfb = ctx->draw_buffer; 431 struct st_renderbuffer *strb = stfb->strb; 432 433 /* first finish all pending rendering */ 434 vgFinish(); 435 436 dest_surface = pipe->screen->get_tex_surface(pipe->screen, 437 stfb->blend_texture, 438 0, 0, 0, 439 PIPE_BUFFER_USAGE_GPU_WRITE); 440 /* flip it, because we want to use it as a sampler */ 441 util_blit_pixels_tex(ctx->blit, 442 strb->texture, 443 0, strb->height, 444 strb->width, 0, 445 dest_surface, 446 0, 0, 447 strb->width, strb->height, 448 0.0, PIPE_TEX_MIPFILTER_NEAREST); 449 450 if (dest_surface) 451 pipe_surface_reference(&dest_surface, NULL); 452 453 /* make sure it's complete */ 454 vgFinish(); 455} 456 457 458void vg_prepare_blend_surface_from_mask(struct vg_context *ctx) 459{ 460 struct pipe_surface *dest_surface = NULL; 461 struct pipe_context *pipe = ctx->pipe; 462 struct st_framebuffer *stfb = ctx->draw_buffer; 463 struct st_renderbuffer *strb = stfb->strb; 464 465 vg_validate_state(ctx); 466 467 /* first finish all pending rendering */ 468 vgFinish(); 469 470 dest_surface = pipe->screen->get_tex_surface(pipe->screen, 471 stfb->blend_texture, 472 0, 0, 0, 473 PIPE_BUFFER_USAGE_GPU_WRITE); 474 475 /* flip it, because we want to use it as a sampler */ 476 util_blit_pixels_tex(ctx->blit, 477 stfb->alpha_mask, 478 0, strb->height, 479 strb->width, 0, 480 dest_surface, 481 0, 0, 482 strb->width, strb->height, 483 0.0, PIPE_TEX_MIPFILTER_NEAREST); 484 485 /* make sure it's complete */ 486 vgFinish(); 487 488 if (dest_surface) 489 pipe_surface_reference(&dest_surface, NULL); 490} 491 492void * vg_plain_vs(struct vg_context *ctx) 493{ 494 if (!ctx->plain_vs) { 495 ctx->plain_vs = shader_create_from_text(ctx->pipe, 496 vs_plain_asm, 497 200, 498 PIPE_SHADER_VERTEX); 499 } 500 501 return ctx->plain_vs->driver; 502} 503 504 505void * vg_clear_vs(struct vg_context *ctx) 506{ 507 if (!ctx->clear_vs) { 508 ctx->clear_vs = shader_create_from_text(ctx->pipe, 509 vs_clear_asm, 510 200, 511 PIPE_SHADER_VERTEX); 512 } 513 514 return ctx->clear_vs->driver; 515} 516 517void * vg_texture_vs(struct vg_context *ctx) 518{ 519 if (!ctx->texture_vs) { 520 ctx->texture_vs = shader_create_from_text(ctx->pipe, 521 vs_texture_asm, 522 200, 523 PIPE_SHADER_VERTEX); 524 } 525 526 return ctx->texture_vs->driver; 527} 528 529void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation) 530{ 531 struct pipe_viewport_state viewport; 532 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 533 VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f; 534 535 viewport.scale[0] = fb->width / 2.f; 536 viewport.scale[1] = fb->height / y_scale; 537 viewport.scale[2] = 1.0; 538 viewport.scale[3] = 1.0; 539 viewport.translate[0] = fb->width / 2.f; 540 viewport.translate[1] = fb->height / 2.f; 541 viewport.translate[2] = 0.0; 542 viewport.translate[3] = 0.0; 543 544 cso_set_viewport(ctx->cso_context, &viewport); 545} 546