vg_context.c revision 0d3a6a505d537b879f31be0ed14fa8577717efaf
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_buffer **cbuf = &ctx->mask.cbuf; 126 struct pipe_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) 135 pipe_buffer_reference(cbuf, NULL); 136 137 if (*vsbuf) 138 pipe_buffer_reference(vsbuf, 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->rt[0].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 cso_restore_blend(ctx->cso_context); 290 cso_restore_fragment_shader(ctx->cso_context); 291 292 dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */ 293 dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/ 294 dsa->depth.func = PIPE_FUNC_GEQUAL; 295 } 296} 297 298void vg_validate_state(struct vg_context *ctx) 299{ 300 if ((ctx->state.dirty & BLEND_DIRTY)) { 301 struct pipe_blend_state *blend = &ctx->state.g3d.blend; 302 memset(blend, 0, sizeof(struct pipe_blend_state)); 303 blend->rt[0].blend_enable = 1; 304 blend->rt[0].colormask = PIPE_MASK_RGBA; 305 306 switch (ctx->state.vg.blend_mode) { 307 case VG_BLEND_SRC: 308 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 309 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 310 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 311 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 312 blend->rt[0].blend_enable = 0; 313 break; 314 case VG_BLEND_SRC_OVER: 315 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 316 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 317 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 318 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA; 319 break; 320 case VG_BLEND_DST_OVER: 321 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; 322 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA; 323 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; 324 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA; 325 break; 326 case VG_BLEND_SRC_IN: 327 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; 328 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA; 329 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 330 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 331 break; 332 case VG_BLEND_DST_IN: 333 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO; 334 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO; 335 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 336 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA; 337 break; 338 case VG_BLEND_MULTIPLY: 339 case VG_BLEND_SCREEN: 340 case VG_BLEND_DARKEN: 341 case VG_BLEND_LIGHTEN: 342 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 343 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 344 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; 345 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; 346 blend->rt[0].blend_enable = 0; 347 break; 348 case VG_BLEND_ADDITIVE: 349 blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE; 350 blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE; 351 blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE; 352 blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE; 353 break; 354 default: 355 assert(!"not implemented blend mode"); 356 } 357 cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend); 358 } 359 if ((ctx->state.dirty & RASTERIZER_DIRTY)) { 360 struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer; 361 memset(raster, 0, sizeof(struct pipe_rasterizer_state)); 362 raster->gl_rasterization_rules = 1; 363 cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer); 364 } 365 if ((ctx->state.dirty & VIEWPORT_DIRTY)) { 366 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 367 const VGint param_bytes = 8 * sizeof(VGfloat); 368 VGfloat vs_consts[8] = { 369 2.f/fb->width, 2.f/fb->height, 1, 1, 370 -1, -1, 0, 0 371 }; 372 struct pipe_buffer **cbuf = &ctx->vs_const_buffer; 373 374 vg_set_viewport(ctx, VEGA_Y0_BOTTOM); 375 376 pipe_buffer_reference(cbuf, NULL); 377 *cbuf = pipe_buffer_create(ctx->pipe->screen, 16, 378 PIPE_BUFFER_USAGE_CONSTANT, 379 param_bytes); 380 381 if (*cbuf) { 382 st_no_flush_pipe_buffer_write(ctx, *cbuf, 383 0, param_bytes, vs_consts); 384 } 385 ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, *cbuf); 386 } 387 if ((ctx->state.dirty & VS_DIRTY)) { 388 cso_set_vertex_shader_handle(ctx->cso_context, 389 vg_plain_vs(ctx)); 390 } 391 392 /* must be last because it renders to the depth buffer*/ 393 if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) { 394 update_clip_state(ctx); 395 cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa); 396 } 397 398 shader_set_masking(ctx->shader, ctx->state.vg.masking); 399 shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode); 400 401 ctx->state.dirty = NONE_DIRTY; 402} 403 404VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type) 405{ 406 struct vg_object *obj = ptr; 407 if (ptr && is_aligned(obj) && obj->type == type) 408 return VG_TRUE; 409 else 410 return VG_FALSE; 411} 412 413void vg_set_error(struct vg_context *ctx, 414 VGErrorCode code) 415{ 416 /*vgGetError returns the oldest error code provided by 417 * an API call on the current context since the previous 418 * call to vgGetError on that context (or since the creation 419 of the context).*/ 420 if (ctx->_error == VG_NO_ERROR) 421 ctx->_error = code; 422} 423 424void vg_prepare_blend_surface(struct vg_context *ctx) 425{ 426 struct pipe_surface *dest_surface = NULL; 427 struct pipe_context *pipe = ctx->pipe; 428 struct st_framebuffer *stfb = ctx->draw_buffer; 429 struct st_renderbuffer *strb = stfb->strb; 430 431 /* first finish all pending rendering */ 432 vgFinish(); 433 434 dest_surface = pipe->screen->get_tex_surface(pipe->screen, 435 stfb->blend_texture, 436 0, 0, 0, 437 PIPE_BUFFER_USAGE_GPU_WRITE); 438 /* flip it, because we want to use it as a sampler */ 439 util_blit_pixels_tex(ctx->blit, 440 strb->texture, 441 0, strb->height, 442 strb->width, 0, 443 dest_surface, 444 0, 0, 445 strb->width, strb->height, 446 0.0, PIPE_TEX_MIPFILTER_NEAREST); 447 448 if (dest_surface) 449 pipe_surface_reference(&dest_surface, NULL); 450 451 /* make sure it's complete */ 452 vgFinish(); 453} 454 455 456void vg_prepare_blend_surface_from_mask(struct vg_context *ctx) 457{ 458 struct pipe_surface *dest_surface = NULL; 459 struct pipe_context *pipe = ctx->pipe; 460 struct st_framebuffer *stfb = ctx->draw_buffer; 461 struct st_renderbuffer *strb = stfb->strb; 462 463 vg_validate_state(ctx); 464 465 /* first finish all pending rendering */ 466 vgFinish(); 467 468 dest_surface = pipe->screen->get_tex_surface(pipe->screen, 469 stfb->blend_texture, 470 0, 0, 0, 471 PIPE_BUFFER_USAGE_GPU_WRITE); 472 473 /* flip it, because we want to use it as a sampler */ 474 util_blit_pixels_tex(ctx->blit, 475 stfb->alpha_mask, 476 0, strb->height, 477 strb->width, 0, 478 dest_surface, 479 0, 0, 480 strb->width, strb->height, 481 0.0, PIPE_TEX_MIPFILTER_NEAREST); 482 483 /* make sure it's complete */ 484 vgFinish(); 485 486 if (dest_surface) 487 pipe_surface_reference(&dest_surface, NULL); 488} 489 490void * vg_plain_vs(struct vg_context *ctx) 491{ 492 if (!ctx->plain_vs) { 493 ctx->plain_vs = shader_create_from_text(ctx->pipe, 494 vs_plain_asm, 495 200, 496 PIPE_SHADER_VERTEX); 497 } 498 499 return ctx->plain_vs->driver; 500} 501 502 503void * vg_clear_vs(struct vg_context *ctx) 504{ 505 if (!ctx->clear_vs) { 506 ctx->clear_vs = shader_create_from_text(ctx->pipe, 507 vs_clear_asm, 508 200, 509 PIPE_SHADER_VERTEX); 510 } 511 512 return ctx->clear_vs->driver; 513} 514 515void * vg_texture_vs(struct vg_context *ctx) 516{ 517 if (!ctx->texture_vs) { 518 ctx->texture_vs = shader_create_from_text(ctx->pipe, 519 vs_texture_asm, 520 200, 521 PIPE_SHADER_VERTEX); 522 } 523 524 return ctx->texture_vs->driver; 525} 526 527void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation) 528{ 529 struct pipe_viewport_state viewport; 530 struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb; 531 VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f; 532 533 viewport.scale[0] = fb->width / 2.f; 534 viewport.scale[1] = fb->height / y_scale; 535 viewport.scale[2] = 1.0; 536 viewport.scale[3] = 1.0; 537 viewport.translate[0] = fb->width / 2.f; 538 viewport.translate[1] = fb->height / 2.f; 539 viewport.translate[2] = 0.0; 540 viewport.translate[3] = 0.0; 541 542 cso_set_viewport(ctx->cso_context, &viewport); 543} 544