1 /**************************************************************************
3 * Copyright 2009 VMware, Inc. All Rights Reserved.
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:
13 * The above copyright notice and this permission notice (including the
14 * next paragraph) shall be included in all copies or substantial portions
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.
25 **************************************************************************/
31 #include "shaders_cache.h"
34 #include "st_inlines.h"
36 #include "pipe/p_context.h"
37 #include "pipe/p_screen.h"
38 #include "util/u_inlines.h"
39 #include "util/u_format.h"
40 #include "util/u_memory.h"
41 #include "util/u_sampler.h"
43 struct vg_mask_layer
{
44 struct vg_object base
;
49 struct pipe_sampler_view
*sampler_view
;
52 static INLINE
struct pipe_surface
*
53 alpha_mask_surface(struct vg_context
*ctx
, int usage
)
55 struct pipe_screen
*screen
= ctx
->pipe
->screen
;
56 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
57 return screen
->get_tex_surface(screen
,
58 stfb
->alpha_mask_view
->texture
,
63 static INLINE VGboolean
64 intersect_rectangles(VGint dwidth
, VGint dheight
,
65 VGint swidth
, VGint sheight
,
67 VGint twidth
, VGint theight
,
71 if (tx
+ twidth
<= 0 || tx
>= dwidth
)
73 if (ty
+ theight
<= 0 || ty
>= dheight
)
85 location
[2] = MIN2(tx
+ swidth
, MIN2(dwidth
, tx
+ twidth
));
86 offsets
[2] = location
[2];
88 offsets
[2] = MIN2(twidth
, MIN2(dwidth
- tx
, swidth
));
89 location
[2] = offsets
[2];
96 location
[3] = MIN2(ty
+ sheight
, MIN2(dheight
, ty
+ theight
));
97 offsets
[3] = location
[3];
99 offsets
[3] = MIN2(theight
, MIN2(dheight
- ty
, sheight
));
100 location
[3] = offsets
[3];
107 static void read_alpha_mask(void * data
, VGint dataStride
,
108 VGImageFormat dataFormat
,
110 VGint width
, VGint height
)
112 struct vg_context
*ctx
= vg_current_context();
113 struct pipe_context
*pipe
= ctx
->pipe
;
114 struct pipe_screen
*screen
= pipe
->screen
;
116 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
117 struct st_renderbuffer
*strb
= stfb
->alpha_mask
;
119 VGfloat temp
[VEGA_MAX_IMAGE_WIDTH
][4];
120 VGfloat
*df
= (VGfloat
*)temp
;
121 VGint y
= (stfb
->height
- sy
) - 1, yStep
= -1;
123 VGubyte
*dst
= (VGubyte
*)data
;
124 VGint xoffset
= 0, yoffset
= 0;
126 /* make sure rendering has completed */
127 pipe
->flush(pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
130 xoffset
*= _vega_size_for_format(dataFormat
);
138 y
= (stfb
->height
- sy
) - 1;
139 yoffset
*= dataStride
;
143 struct pipe_surface
*surf
;
145 surf
= screen
->get_tex_surface(screen
, strb
->texture
, 0, 0, 0,
146 PIPE_BIND_TRANSFER_READ
);
148 /* Do a row at a time to flip image data vertically */
149 for (i
= 0; i
< height
; i
++) {
151 debug_printf("%d-%d == %d\n", sy
, height
, y
);
153 pipe_get_tile_rgba(surf
, sx
, y
, width
, 1, df
);
155 _vega_pack_rgba_span_float(ctx
, width
, temp
, dataFormat
,
156 dst
+ yoffset
+ xoffset
);
160 pipe_surface_reference(&surf
, NULL
);
164 void save_alpha_to_file(const char *filename
)
166 struct vg_context
*ctx
= vg_current_context();
167 struct st_framebuffer
*stfb
= ctx
->draw_buffer
;
171 data
= malloc(sizeof(int) * stfb
->width
* stfb
->height
);
172 read_alpha_mask(data
, stfb
->width
* sizeof(int),
174 0, 0, stfb
->width
, stfb
->height
);
175 fprintf(stderr
, "/*---------- start */\n");
176 fprintf(stderr
, "const int image_width = %d;\n",
178 fprintf(stderr
, "const int image_height = %d;\n",
180 fprintf(stderr
, "const int image_data = {\n");
181 for (i
= 0; i
< stfb
->height
; ++i
) {
182 for (j
= 0; j
< stfb
->width
; ++j
) {
183 int rgba
= data
[i
* stfb
->height
+ j
];
186 argb
|= ((rgba
& 0xff) << 24);
187 fprintf(stderr
, "0x%x, ", argb
);
189 fprintf(stderr
, "\n");
191 fprintf(stderr
, "};\n");
192 fprintf(stderr
, "/*---------- end */\n");
196 /* setup mask shader */
197 static void *setup_mask_operation(VGMaskOperation operation
)
199 struct vg_context
*ctx
= vg_current_context();
203 case VG_UNION_MASK
: {
204 if (!ctx
->mask
.union_fs
) {
205 ctx
->mask
.union_fs
= shader_create_from_text(ctx
->pipe
,
208 PIPE_SHADER_FRAGMENT
);
210 shader
= ctx
->mask
.union_fs
->driver
;
213 case VG_INTERSECT_MASK
: {
214 if (!ctx
->mask
.intersect_fs
) {
215 ctx
->mask
.intersect_fs
= shader_create_from_text(ctx
->pipe
,
218 PIPE_SHADER_FRAGMENT
);
220 shader
= ctx
->mask
.intersect_fs
->driver
;
223 case VG_SUBTRACT_MASK
: {
224 if (!ctx
->mask
.subtract_fs
) {
225 ctx
->mask
.subtract_fs
= shader_create_from_text(ctx
->pipe
,
228 PIPE_SHADER_FRAGMENT
);
230 shader
= ctx
->mask
.subtract_fs
->driver
;
234 if (!ctx
->mask
.set_fs
) {
235 ctx
->mask
.set_fs
= shader_create_from_text(ctx
->pipe
,
238 PIPE_SHADER_FRAGMENT
);
240 shader
= ctx
->mask
.set_fs
->driver
;
251 static void mask_resource_fill(struct pipe_resource
*dst
,
252 int x
, int y
, int width
, int height
,
255 struct vg_context
*ctx
= vg_current_context();
256 VGfloat color
[4] = { 0.0f
, 0.0f
, 0.0f
, coverage
};
268 fs
= shaders_cache_fill(ctx
->sc
, VEGA_SOLID_FILL_SHADER
);
270 if (renderer_filter_begin(ctx
->renderer
, dst
, VG_FALSE
,
271 ~0, NULL
, NULL
, 0, fs
, (const void *) color
, sizeof(color
))) {
272 renderer_filter(ctx
->renderer
, x
, y
, width
, height
, 0, 0, 0, 0);
273 renderer_filter_end(ctx
->renderer
);
277 save_alpha_to_file(0);
282 static void mask_using_texture(struct pipe_sampler_view
*sampler_view
,
283 VGMaskOperation operation
,
285 VGint width
, VGint height
)
287 struct vg_context
*ctx
= vg_current_context();
288 struct pipe_resource
*dst
= ctx
->draw_buffer
->alpha_mask_view
->texture
;
289 struct pipe_resource
*texture
= sampler_view
->texture
;
290 const struct pipe_sampler_state
*samplers
[2];
291 struct pipe_sampler_view
*views
[2];
292 struct pipe_sampler_state sampler
;
293 VGint offsets
[4], loc
[4];
294 const VGfloat ones
[4] = {1.f
, 1.f
, 1.f
, 1.f
};
297 if (!intersect_rectangles(dst
->width0
, dst
->height0
,
298 texture
->width0
, texture
->height0
,
303 debug_printf("Offset = [%d, %d, %d, %d]\n", offsets
[0],
304 offsets
[1], offsets
[2], offsets
[3]);
305 debug_printf("Locati = [%d, %d, %d, %d]\n", loc
[0],
306 loc
[1], loc
[2], loc
[3]);
309 sampler
= ctx
->mask
.sampler
;
310 sampler
.normalized_coords
= 1;
311 samplers
[0] = &sampler
;
312 views
[0] = sampler_view
;
314 /* prepare our blend surface */
315 vg_prepare_blend_surface_from_mask(ctx
);
316 samplers
[1] = &ctx
->mask
.sampler
;
317 views
[1] = ctx
->draw_buffer
->blend_texture_view
;
319 fs
= setup_mask_operation(operation
);
321 if (renderer_filter_begin(ctx
->renderer
, dst
, VG_FALSE
,
322 ~0, samplers
, views
, 2, fs
, (const void *) ones
, sizeof(ones
))) {
323 renderer_filter(ctx
->renderer
,
324 loc
[0], loc
[1], loc
[2], loc
[3],
325 offsets
[0], offsets
[1], offsets
[2], offsets
[3]);
326 renderer_filter_end(ctx
->renderer
);
331 #ifdef OPENVG_VERSION_1_1
333 struct vg_mask_layer
* mask_layer_create(VGint width
, VGint height
)
335 struct vg_context
*ctx
= vg_current_context();
336 struct vg_mask_layer
*mask
= 0;
338 mask
= CALLOC_STRUCT(vg_mask_layer
);
339 vg_init_object(&mask
->base
, ctx
, VG_OBJECT_MASK
);
341 mask
->height
= height
;
344 struct pipe_resource pt
;
345 struct pipe_context
*pipe
= ctx
->pipe
;
346 struct pipe_screen
*screen
= ctx
->pipe
->screen
;
347 struct pipe_sampler_view view_templ
;
348 struct pipe_sampler_view
*view
= NULL
;
349 struct pipe_resource
*texture
;
351 memset(&pt
, 0, sizeof(pt
));
352 pt
.target
= PIPE_TEXTURE_2D
;
353 pt
.format
= PIPE_FORMAT_B8G8R8A8_UNORM
;
358 pt
.bind
= PIPE_BIND_SAMPLER_VIEW
;
360 texture
= screen
->resource_create(screen
, &pt
);
363 u_sampler_view_default_template(&view_templ
, texture
, texture
->format
);
364 view
= pipe
->create_sampler_view(pipe
, texture
, &view_templ
);
366 pipe_resource_reference(&texture
, NULL
);
367 mask
->sampler_view
= view
;
370 vg_context_add_object(ctx
, VG_OBJECT_MASK
, mask
);
375 void mask_layer_destroy(struct vg_mask_layer
*layer
)
377 struct vg_context
*ctx
= vg_current_context();
379 vg_context_remove_object(ctx
, VG_OBJECT_MASK
, layer
);
380 pipe_sampler_view_reference(&layer
->sampler_view
, NULL
);
384 void mask_layer_fill(struct vg_mask_layer
*layer
,
386 VGint width
, VGint height
,
389 VGfloat alpha_color
[4] = {0, 0, 0, 0};
391 alpha_color
[3] = value
;
393 mask_resource_fill(layer
->sampler_view
->texture
,
394 x
, y
, width
, height
, value
);
397 void mask_copy(struct vg_mask_layer
*layer
,
400 VGint width
, VGint height
)
402 struct vg_context
*ctx
= vg_current_context();
403 struct pipe_sampler_view
*src
= ctx
->draw_buffer
->alpha_mask_view
;
404 struct pipe_surface
*surf
;
406 /* get the destination surface */
407 surf
= ctx
->pipe
->screen
->get_tex_surface(ctx
->pipe
->screen
,
408 layer
->sampler_view
->texture
, 0, 0, 0, PIPE_BIND_RENDER_TARGET
);
409 if (surf
&& renderer_copy_begin(ctx
->renderer
, surf
, VG_FALSE
, src
)) {
410 renderer_copy(ctx
->renderer
,
411 dx
, dy
, width
, height
,
412 sx
, sy
, width
, height
);
413 renderer_copy_end(ctx
->renderer
);
416 pipe_surface_reference(&surf
, NULL
);
419 static void mask_layer_render_to(struct vg_mask_layer
*layer
,
421 VGbitfield paint_modes
)
424 struct vg_context
*ctx
= vg_current_context();
425 const VGfloat fill_color
[4] = {1.f
, 1.f
, 1.f
, 1.f
};
426 struct pipe_screen
*screen
= ctx
->pipe
->screen
;
427 struct matrix
*mat
= &ctx
->state
.vg
.path_user_to_surface_matrix
;
428 struct pipe_surface
*surface
;
430 surface
= screen
->get_tex_surface(screen
, layer
->sampler_view
->texture
, 0, 0, 0,
431 PIPE_BIND_RENDER_TARGET
);
433 cso_save_framebuffer(ctx
->cso_context
);
434 cso_save_fragment_shader(ctx
->cso_context
);
437 setup_mask_fill(fill_color
);
438 setup_mask_framebuffer(surface
, layer
->width
, layer
->height
);
440 if (paint_modes
& VG_FILL_PATH
) {
441 path_fill(path
, mat
);
444 if (paint_modes
& VG_STROKE_PATH
){
445 path_stroke(path
, mat
);
449 /* make sure rendering has completed */
450 ctx
->pipe
->flush(ctx
->pipe
, PIPE_FLUSH_RENDER_CACHE
, NULL
);
452 cso_restore_framebuffer(ctx
->cso_context
);
453 cso_restore_fragment_shader(ctx
->cso_context
);
454 ctx
->state
.dirty
|= BLEND_DIRTY
;
456 pipe_surface_reference(&surface
, NULL
);
460 void mask_render_to(struct path
*path
,
461 VGbitfield paint_modes
,
462 VGMaskOperation operation
)
464 struct vg_context
*ctx
= vg_current_context();
465 struct st_framebuffer
*fb_buffers
= ctx
->draw_buffer
;
466 struct vg_mask_layer
*temp_layer
;
469 width
= fb_buffers
->alpha_mask_view
->texture
->width0
;
470 height
= fb_buffers
->alpha_mask_view
->texture
->width0
;
472 temp_layer
= mask_layer_create(width
, height
);
474 mask_layer_render_to(temp_layer
, path
, paint_modes
);
476 mask_using_layer(temp_layer
, 0, 0, width
, height
,
479 mask_layer_destroy(temp_layer
);
482 void mask_using_layer(struct vg_mask_layer
*layer
,
483 VGMaskOperation operation
,
485 VGint width
, VGint height
)
487 mask_using_texture(layer
->sampler_view
, operation
,
488 x
, y
, width
, height
);
491 VGint
mask_layer_width(struct vg_mask_layer
*layer
)
496 VGint
mask_layer_height(struct vg_mask_layer
*layer
)
498 return layer
->height
;
504 void mask_using_image(struct vg_image
*image
,
505 VGMaskOperation operation
,
507 VGint width
, VGint height
)
509 mask_using_texture(image
->sampler_view
, operation
,
510 x
, y
, width
, height
);
513 void mask_fill(VGint x
, VGint y
, VGint width
, VGint height
,
516 struct vg_context
*ctx
= vg_current_context();
519 debug_printf("mask_fill(%d, %d, %d, %d) with rgba(%f, %f, %f, %f)\n",
521 0.0f
, 0.0f
, 0.0f
, value
);
524 mask_resource_fill(ctx
->draw_buffer
->alpha_mask_view
->texture
,
525 x
, y
, width
, height
, value
);
528 VGint
mask_bind_samplers(struct pipe_sampler_state
**samplers
,
529 struct pipe_sampler_view
**sampler_views
)
531 struct vg_context
*ctx
= vg_current_context();
533 if (ctx
->state
.vg
.masking
) {
534 struct st_framebuffer
*fb_buffers
= ctx
->draw_buffer
;
536 samplers
[1] = &ctx
->mask
.sampler
;
537 sampler_views
[1] = fb_buffers
->alpha_mask_view
;