vg_context.c revision b730f0fc52a208b5f2a308199724ab02aa391fec
12a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)/**************************************************************************
22a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
32a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Copyright 2009 VMware, Inc.  All Rights Reserved.
42a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
52a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * Permission is hereby granted, free of charge, to any person obtaining a
62a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * copy of this software and associated documentation files (the
72a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * "Software"), to deal in the Software without restriction, including
82a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * without limitation the rights to use, copy, modify, merge, publish,
9a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) * distribute, sub license, and/or sell copies of the Software, and to
102a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * permit persons to whom the Software is furnished to do so, subject to
112a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * the following conditions:
122a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
132a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * The above copyright notice and this permission notice (including the
142a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * next paragraph) shall be included in all copies or substantial portions
152a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * of the Software.
162a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
172a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
182a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
192a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
202a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
212a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
222a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
232a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
242a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles) *
25a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles) **************************************************************************/
26a1401311d1ab56c4ed0a474bd38c108f75cb0cd9Torne (Richard Coles)
272a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "vg_context.h"
282a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
292a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "paint.h"
302a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "renderer.h"
312a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "shaders_cache.h"
322a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "shader.h"
332a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "asm_util.h"
342a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "st_inlines.h"
352a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "vg_manager.h"
362a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)#include "api.h"
372a99a7e74a7f215066514fe81d2bfa6639d9edddTorne (Richard Coles)
38#include "pipe/p_context.h"
39#include "util/u_inlines.h"
40
41#include "cso_cache/cso_context.h"
42
43#include "util/u_simple_shaders.h"
44#include "util/u_memory.h"
45#include "util/u_blit.h"
46#include "util/u_sampler.h"
47
48struct vg_context *_vg_context = 0;
49
50struct vg_context * vg_current_context(void)
51{
52   return _vg_context;
53}
54
55static void init_clear(struct vg_context *st)
56{
57   struct pipe_context *pipe = st->pipe;
58
59   /* rasterizer state: bypass clipping */
60   memset(&st->clear.raster, 0, sizeof(st->clear.raster));
61   st->clear.raster.gl_rasterization_rules = 1;
62
63   /* fragment shader state: color pass-through program */
64   st->clear.fs =
65      util_make_fragment_passthrough_shader(pipe);
66}
67
68/**
69 * A depth/stencil rb will be needed regardless of what the visual says.
70 */
71static boolean
72choose_depth_stencil_format(struct vg_context *ctx)
73{
74   struct pipe_screen *screen = ctx->pipe->screen;
75   enum pipe_format formats[] = {
76      PIPE_FORMAT_Z24_UNORM_S8_USCALED,
77      PIPE_FORMAT_S8_USCALED_Z24_UNORM,
78      PIPE_FORMAT_NONE
79   };
80   enum pipe_format *fmt;
81
82   for (fmt = formats; *fmt != PIPE_FORMAT_NONE; fmt++) {
83      if (screen->is_format_supported(screen, *fmt,
84               PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0))
85         break;
86   }
87
88   ctx->ds_format = *fmt;
89
90   return (ctx->ds_format != PIPE_FORMAT_NONE);
91}
92
93void vg_set_current_context(struct vg_context *ctx)
94{
95   _vg_context = ctx;
96   api_make_dispatch_current((ctx) ? ctx->dispatch : NULL);
97}
98
99struct vg_context * vg_create_context(struct pipe_context *pipe,
100                                      const void *visual,
101                                      struct vg_context *share)
102{
103   struct vg_context *ctx;
104   unsigned i;
105
106   ctx = CALLOC_STRUCT(vg_context);
107
108   ctx->pipe = pipe;
109   if (!choose_depth_stencil_format(ctx)) {
110      FREE(ctx);
111      return NULL;
112   }
113
114   ctx->dispatch = api_create_dispatch();
115
116   vg_init_state(&ctx->state.vg);
117   ctx->state.dirty = ALL_DIRTY;
118
119   ctx->cso_context = cso_create_context(pipe);
120
121   init_clear(ctx);
122
123   ctx->default_paint = paint_create(ctx);
124   ctx->state.vg.stroke_paint = ctx->default_paint;
125   ctx->state.vg.fill_paint = ctx->default_paint;
126
127
128   ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
129   ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
130   ctx->mask.sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
131   ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
132   ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
133   ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
134   ctx->mask.sampler.normalized_coords = 0;
135
136   ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
137   ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
138   ctx->blend_sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
139   ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
140   ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
141   ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
142   ctx->blend_sampler.normalized_coords = 0;
143
144   for (i = 0; i < 2; i++) {
145      ctx->velems[i].src_offset = i * 4 * sizeof(float);
146      ctx->velems[i].instance_divisor = 0;
147      ctx->velems[i].vertex_buffer_index = 0;
148      ctx->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
149   }
150
151   vg_set_error(ctx, VG_NO_ERROR);
152
153   ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create();
154   ctx->owned_objects[VG_OBJECT_IMAGE] = cso_hash_create();
155   ctx->owned_objects[VG_OBJECT_MASK] = cso_hash_create();
156   ctx->owned_objects[VG_OBJECT_FONT] = cso_hash_create();
157   ctx->owned_objects[VG_OBJECT_PATH] = cso_hash_create();
158
159   ctx->renderer = renderer_create(ctx);
160   ctx->sc = shaders_cache_create(ctx);
161   ctx->shader = shader_create(ctx);
162
163   ctx->blit = util_create_blit(ctx->pipe, ctx->cso_context);
164
165   return ctx;
166}
167
168void vg_destroy_context(struct vg_context *ctx)
169{
170   struct pipe_resource **cbuf = &ctx->mask.cbuf;
171   struct pipe_resource **vsbuf = &ctx->vs_const_buffer;
172
173   util_destroy_blit(ctx->blit);
174   renderer_destroy(ctx->renderer);
175   shaders_cache_destroy(ctx->sc);
176   shader_destroy(ctx->shader);
177   paint_destroy(ctx->default_paint);
178
179   if (*cbuf)
180      pipe_resource_reference(cbuf, NULL);
181
182   if (*vsbuf)
183      pipe_resource_reference(vsbuf, NULL);
184
185   if (ctx->clear.fs) {
186      cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs);
187      ctx->clear.fs = NULL;
188   }
189
190   if (ctx->plain_vs) {
191      vg_shader_destroy(ctx, ctx->plain_vs);
192      ctx->plain_vs = NULL;
193   }
194   if (ctx->clear_vs) {
195      vg_shader_destroy(ctx, ctx->clear_vs);
196      ctx->clear_vs = NULL;
197   }
198   if (ctx->texture_vs) {
199      vg_shader_destroy(ctx, ctx->texture_vs);
200      ctx->texture_vs = NULL;
201   }
202
203   if (ctx->pass_through_depth_fs)
204      vg_shader_destroy(ctx, ctx->pass_through_depth_fs);
205   if (ctx->mask.union_fs)
206      vg_shader_destroy(ctx, ctx->mask.union_fs);
207   if (ctx->mask.intersect_fs)
208      vg_shader_destroy(ctx, ctx->mask.intersect_fs);
209   if (ctx->mask.subtract_fs)
210      vg_shader_destroy(ctx, ctx->mask.subtract_fs);
211   if (ctx->mask.set_fs)
212      vg_shader_destroy(ctx, ctx->mask.set_fs);
213
214   cso_release_all(ctx->cso_context);
215   cso_destroy_context(ctx->cso_context);
216
217   cso_hash_delete(ctx->owned_objects[VG_OBJECT_PAINT]);
218   cso_hash_delete(ctx->owned_objects[VG_OBJECT_IMAGE]);
219   cso_hash_delete(ctx->owned_objects[VG_OBJECT_MASK]);
220   cso_hash_delete(ctx->owned_objects[VG_OBJECT_FONT]);
221   cso_hash_delete(ctx->owned_objects[VG_OBJECT_PATH]);
222
223   api_destroy_dispatch(ctx->dispatch);
224
225   FREE(ctx);
226}
227
228void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_object_type type)
229{
230   obj->type = type;
231   obj->ctx = ctx;
232}
233
234VGboolean vg_context_is_object_valid(struct vg_context *ctx,
235                                enum vg_object_type type,
236                                void *ptr)
237{
238    if (ctx) {
239       struct cso_hash *hash = ctx->owned_objects[type];
240       if (!hash)
241          return VG_FALSE;
242       return cso_hash_contains(hash, (unsigned)(long)ptr);
243    }
244    return VG_FALSE;
245}
246
247void vg_context_add_object(struct vg_context *ctx,
248                           enum vg_object_type type,
249                           void *ptr)
250{
251    if (ctx) {
252       struct cso_hash *hash = ctx->owned_objects[type];
253       if (!hash)
254          return;
255       cso_hash_insert(hash, (unsigned)(long)ptr, ptr);
256    }
257}
258
259void vg_context_remove_object(struct vg_context *ctx,
260                              enum vg_object_type type,
261                              void *ptr)
262{
263   if (ctx) {
264      struct cso_hash *hash = ctx->owned_objects[type];
265      if (!hash)
266         return;
267      cso_hash_take(hash, (unsigned)(long)ptr);
268   }
269}
270
271void vg_validate_state(struct vg_context *ctx)
272{
273   vg_manager_validate_framebuffer(ctx);
274
275   renderer_validate(ctx->renderer, ctx->state.dirty,
276         ctx->draw_buffer, &ctx->state.vg);
277
278   ctx->state.dirty = NONE_DIRTY;
279
280   shader_set_masking(ctx->shader, ctx->state.vg.masking);
281   shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
282}
283
284VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)
285{
286   struct vg_object *obj = ptr;
287   if (ptr && is_aligned(obj) && obj->type == type)
288      return VG_TRUE;
289   else
290      return VG_FALSE;
291}
292
293void vg_set_error(struct vg_context *ctx,
294                  VGErrorCode code)
295{
296   /*vgGetError returns the oldest error code provided by
297    * an API call on the current context since the previous
298    * call to vgGetError on that context (or since the creation
299    of the context).*/
300   if (ctx->_error == VG_NO_ERROR)
301      ctx->_error = code;
302}
303
304void vg_prepare_blend_surface(struct vg_context *ctx)
305{
306   struct pipe_surface *dest_surface = NULL;
307   struct pipe_context *pipe = ctx->pipe;
308   struct pipe_sampler_view *view;
309   struct pipe_sampler_view view_templ;
310   struct st_framebuffer *stfb = ctx->draw_buffer;
311   struct st_renderbuffer *strb = stfb->strb;
312
313   /* first finish all pending rendering */
314   vgFinish();
315
316   u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format);
317   view = pipe->create_sampler_view(pipe, strb->texture, &view_templ);
318
319   dest_surface = pipe->screen->get_tex_surface(pipe->screen,
320                                                stfb->blend_texture_view->texture,
321                                                0, 0, 0,
322                                                PIPE_BIND_RENDER_TARGET);
323   util_blit_pixels_tex(ctx->blit,
324                        view,
325                        0, 0,
326                        strb->width, strb->height,
327                        dest_surface,
328                        0, 0,
329                        strb->width, strb->height,
330                        0.0, PIPE_TEX_MIPFILTER_NEAREST);
331
332   if (dest_surface)
333      pipe_surface_reference(&dest_surface, NULL);
334
335   /* make sure it's complete */
336   vgFinish();
337
338   pipe_sampler_view_reference(&view, NULL);
339}
340
341
342void vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
343{
344   struct pipe_surface *dest_surface = NULL;
345   struct pipe_context *pipe = ctx->pipe;
346   struct st_framebuffer *stfb = ctx->draw_buffer;
347   struct st_renderbuffer *strb = stfb->strb;
348
349   vg_validate_state(ctx);
350
351   /* first finish all pending rendering */
352   vgFinish();
353
354   dest_surface = pipe->screen->get_tex_surface(pipe->screen,
355                                                stfb->blend_texture_view->texture,
356                                                0, 0, 0,
357                                                PIPE_BIND_RENDER_TARGET);
358
359   /* flip it, because we want to use it as a sampler */
360   util_blit_pixels_tex(ctx->blit,
361                        stfb->alpha_mask_view,
362                        0, strb->height,
363                        strb->width, 0,
364                        dest_surface,
365                        0, 0,
366                        strb->width, strb->height,
367                        0.0, PIPE_TEX_MIPFILTER_NEAREST);
368
369   /* make sure it's complete */
370   vgFinish();
371
372   if (dest_surface)
373      pipe_surface_reference(&dest_surface, NULL);
374}
375
376void * vg_plain_vs(struct vg_context *ctx)
377{
378   if (!ctx->plain_vs) {
379      ctx->plain_vs = shader_create_from_text(ctx->pipe,
380                                              vs_plain_asm,
381                                              200,
382                                              PIPE_SHADER_VERTEX);
383   }
384
385   return ctx->plain_vs->driver;
386}
387
388
389void * vg_clear_vs(struct vg_context *ctx)
390{
391   if (!ctx->clear_vs) {
392      ctx->clear_vs = shader_create_from_text(ctx->pipe,
393                                              vs_clear_asm,
394                                              200,
395                                              PIPE_SHADER_VERTEX);
396   }
397
398   return ctx->clear_vs->driver;
399}
400
401void * vg_texture_vs(struct vg_context *ctx)
402{
403   if (!ctx->texture_vs) {
404      ctx->texture_vs = shader_create_from_text(ctx->pipe,
405                                                vs_texture_asm,
406                                                200,
407                                                PIPE_SHADER_VERTEX);
408   }
409
410   return ctx->texture_vs->driver;
411}
412