summaryrefslogtreecommitdiffstats
path: root/src/gallium/state_trackers/vega
diff options
context:
space:
mode:
Diffstat (limited to 'src/gallium/state_trackers/vega')
-rw-r--r--src/gallium/state_trackers/vega/.gitignore1
-rw-r--r--src/gallium/state_trackers/vega/Makefile10
-rw-r--r--src/gallium/state_trackers/vega/SConscript15
-rw-r--r--src/gallium/state_trackers/vega/api.c17
-rw-r--r--src/gallium/state_trackers/vega/api.h5
-rw-r--r--src/gallium/state_trackers/vega/api_context.c7
-rw-r--r--src/gallium/state_trackers/vega/api_filters.c238
-rw-r--r--src/gallium/state_trackers/vega/api_images.c32
-rw-r--r--src/gallium/state_trackers/vega/api_masks.c142
-rw-r--r--src/gallium/state_trackers/vega/api_misc.c4
-rw-r--r--src/gallium/state_trackers/vega/api_params.c5
-rw-r--r--src/gallium/state_trackers/vega/api_path.c3
-rw-r--r--src/gallium/state_trackers/vega/api_text.c122
-rw-r--r--src/gallium/state_trackers/vega/asm_fill.h588
-rw-r--r--src/gallium/state_trackers/vega/asm_util.h51
-rw-r--r--src/gallium/state_trackers/vega/image.c160
-rw-r--r--src/gallium/state_trackers/vega/image.h2
-rw-r--r--src/gallium/state_trackers/vega/mask.c387
-rw-r--r--src/gallium/state_trackers/vega/matrix.h2
-rw-r--r--src/gallium/state_trackers/vega/paint.c125
-rw-r--r--src/gallium/state_trackers/vega/paint.h4
-rw-r--r--src/gallium/state_trackers/vega/path.c72
-rw-r--r--src/gallium/state_trackers/vega/path.h4
-rw-r--r--src/gallium/state_trackers/vega/polygon.c300
-rw-r--r--src/gallium/state_trackers/vega/renderer.c1766
-rw-r--r--src/gallium/state_trackers/vega/renderer.h116
-rw-r--r--src/gallium/state_trackers/vega/shader.c211
-rw-r--r--src/gallium/state_trackers/vega/shader.h7
-rw-r--r--src/gallium/state_trackers/vega/shaders_cache.c199
-rw-r--r--src/gallium/state_trackers/vega/shaders_cache.h73
-rw-r--r--src/gallium/state_trackers/vega/st_inlines.h122
-rw-r--r--src/gallium/state_trackers/vega/text.c250
-rw-r--r--src/gallium/state_trackers/vega/text.h71
-rw-r--r--src/gallium/state_trackers/vega/vg_context.c544
-rw-r--r--src/gallium/state_trackers/vega/vg_context.h66
-rw-r--r--src/gallium/state_trackers/vega/vg_manager.c224
36 files changed, 3353 insertions, 2592 deletions
diff --git a/src/gallium/state_trackers/vega/.gitignore b/src/gallium/state_trackers/vega/.gitignore
new file mode 100644
index 00000000000..c452229f7f4
--- /dev/null
+++ b/src/gallium/state_trackers/vega/.gitignore
@@ -0,0 +1 @@
+api_tmp.h
diff --git a/src/gallium/state_trackers/vega/Makefile b/src/gallium/state_trackers/vega/Makefile
index e0a87151c43..7342c124c28 100644
--- a/src/gallium/state_trackers/vega/Makefile
+++ b/src/gallium/state_trackers/vega/Makefile
@@ -9,6 +9,9 @@ LIBRARY_INCLUDES = \
-I$(TOP)/include \
-I$(TOP)/src/mapi
+LIBRARY_DEFINES = \
+ -DVEGA_VERSION_STRING=\"$(MESA_VERSION)\"
+
C_SOURCES = \
api.c \
api_context.c \
@@ -35,7 +38,14 @@ C_SOURCES = \
renderer.c \
stroker.c \
mask.c \
+ text.c \
shader.c \
shaders_cache.c
+GENERATED_SOURCES := api_tmp.h
+
include ../../Makefile.template
+
+MAPI := $(TOP)/src/mapi
+api_tmp.h: $(MAPI)/mapi/mapi_abi.py $(MAPI)/vgapi/vgapi.csv
+ $(PYTHON2) $< --printer vgapi --mode app $(MAPI)/vgapi/vgapi.csv > $@
diff --git a/src/gallium/state_trackers/vega/SConscript b/src/gallium/state_trackers/vega/SConscript
index a25b8474e4d..4900135a1c5 100644
--- a/src/gallium/state_trackers/vega/SConscript
+++ b/src/gallium/state_trackers/vega/SConscript
@@ -3,11 +3,16 @@
Import('*')
+from sys import executable as python_cmd
+
env = env.Clone()
env.Append(CPPPATH = [
'#/src/mapi',
])
+env.Append(CPPDEFINES = [
+ 'VEGA_VERSION_STRING=',
+])
vega_sources = [
'api.c',
@@ -37,10 +42,16 @@ vega_sources = [
'mask.c',
'shader.c',
'shaders_cache.c',
+ 'text.c',
]
-# vgapi_header must be generated first
-env.Depends(vega_sources, vgapi_header)
+api_tmp = env.CodeGenerate(
+ target = '#/src/gallium/state_trackers/vega/api_tmp.h',
+ script = '#src/mapi/mapi/mapi_abi.py',
+ source = '#src/mapi/vgapi/vgapi.csv',
+ command = python_cmd + ' $SCRIPT --printer vgapi --mode app $SOURCE > $TARGET'
+)
+env.Depends(vega_sources, api_tmp)
st_vega = env.ConvenienceLibrary(
target = 'st_vega',
diff --git a/src/gallium/state_trackers/vega/api.c b/src/gallium/state_trackers/vega/api.c
index bf1d37493af..4bf7c71d453 100644
--- a/src/gallium/state_trackers/vega/api.c
+++ b/src/gallium/state_trackers/vega/api.c
@@ -28,23 +28,10 @@
#include "mapi/mapi.h"
+/* define vega_spec and vega_procs for use with mapi */
+#define API_TMP_DEFINE_SPEC
#include "api.h"
-static const char vega_spec[] =
- "1"
-#define MAPI_ABI_ENTRY(ret, name, params) \
- "\0" #name "\0"
-#define MAPI_ALIAS_ENTRY(alias, ret, name, params) \
- #name "\0"
-#include "vgapi/vgapi_tmp.h"
- "\0";
-
-static const mapi_proc vega_procs[] = {
-#define MAPI_ABI_ENTRY(ret, name, params) \
- (mapi_proc) vega ## name,
-#include "vgapi/vgapi_tmp.h"
-};
-
static void api_init(void)
{
static boolean initialized = FALSE;
diff --git a/src/gallium/state_trackers/vega/api.h b/src/gallium/state_trackers/vega/api.h
index 955508dae9a..459dafb4bb0 100644
--- a/src/gallium/state_trackers/vega/api.h
+++ b/src/gallium/state_trackers/vega/api.h
@@ -33,10 +33,7 @@
#include "VG/vgext.h"
#include "vg_manager.h"
-/* declare the prototypes */
-#define MAPI_ABI_ENTRY(ret, name, params) \
- ret VG_API_ENTRY vega ## name params;
-#include "vgapi/vgapi_tmp.h"
+#include "api_tmp.h"
struct mapi_table;
diff --git a/src/gallium/state_trackers/vega/api_context.c b/src/gallium/state_trackers/vega/api_context.c
index 0d04d8e8718..d6bbda5e075 100644
--- a/src/gallium/state_trackers/vega/api_context.c
+++ b/src/gallium/state_trackers/vega/api_context.c
@@ -73,7 +73,8 @@ void vegaFinish(void)
pipe = ctx->pipe;
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME, &fence);
-
- pipe->screen->fence_finish(pipe->screen, fence, 0);
- pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+ if (fence) {
+ pipe->screen->fence_finish(pipe->screen, fence, 0);
+ pipe->screen->fence_reference(pipe->screen, &fence, NULL);
+ }
}
diff --git a/src/gallium/state_trackers/vega/api_filters.c b/src/gallium/state_trackers/vega/api_filters.c
index 4bd5d7e4bc2..724e38241b5 100644
--- a/src/gallium/state_trackers/vega/api_filters.c
+++ b/src/gallium/state_trackers/vega/api_filters.c
@@ -31,7 +31,6 @@
#include "api.h"
#include "renderer.h"
#include "shaders_cache.h"
-#include "st_inlines.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
@@ -42,7 +41,6 @@
#include "util/u_sampler.h"
#include "util/u_string.h"
-
#include "asm_filters.h"
@@ -73,6 +71,7 @@ static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx,
templ.width0 = color_data_len;
templ.height0 = 1;
templ.depth0 = 1;
+ templ.array_size = 1;
templ.bind = PIPE_BIND_SAMPLER_VIEW;
tex = screen->resource_create(screen, &templ);
@@ -80,9 +79,9 @@ static INLINE struct pipe_resource *create_texture_1d(struct vg_context *ctx,
{ /* upload color_data */
struct pipe_transfer *transfer =
pipe_get_transfer(pipe, tex,
- 0, 0, 0,
- PIPE_TRANSFER_READ_WRITE ,
- 0, 0, tex->width0, tex->height0);
+ 0, 0,
+ PIPE_TRANSFER_READ_WRITE ,
+ 0, 0, tex->width0, tex->height0);
void *map = pipe->transfer_map(pipe, transfer);
memcpy(map, color_data, sizeof(VGint)*color_data_len);
pipe->transfer_unmap(pipe, transfer);
@@ -114,153 +113,11 @@ static INLINE struct pipe_sampler_view *create_texture_1d_view(struct vg_context
return view;
}
-static INLINE struct pipe_surface * setup_framebuffer(struct vg_image *dst)
-{
- struct vg_context *ctx = vg_current_context();
- struct pipe_context *pipe = ctx->pipe;
- struct pipe_framebuffer_state fb;
- struct pipe_surface *dst_surf = pipe->screen->get_tex_surface(
- pipe->screen, dst->sampler_view->texture, 0, 0, 0,
- PIPE_BIND_RENDER_TARGET);
-
- /* drawing dest */
- memset(&fb, 0, sizeof(fb));
- fb.width = dst->x + dst_surf->width;
- fb.height = dst->y + dst_surf->height;
- fb.nr_cbufs = 1;
- fb.cbufs[0] = dst_surf;
- {
- VGint i;
- for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
- fb.cbufs[i] = 0;
- }
- cso_set_framebuffer(ctx->cso_context, &fb);
-
- return dst_surf;
-}
-
-static void setup_viewport(struct vg_image *dst)
-{
- struct vg_context *ctx = vg_current_context();
- vg_set_viewport(ctx, VEGA_Y0_TOP);
-}
-
-static void setup_blend()
-{
- struct vg_context *ctx = vg_current_context();
- struct pipe_blend_state blend;
- memset(&blend, 0, sizeof(blend));
- blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- if (ctx->state.vg.filter_channel_mask & VG_RED)
- blend.rt[0].colormask |= PIPE_MASK_R;
- if (ctx->state.vg.filter_channel_mask & VG_GREEN)
- blend.rt[0].colormask |= PIPE_MASK_G;
- if (ctx->state.vg.filter_channel_mask & VG_BLUE)
- blend.rt[0].colormask |= PIPE_MASK_B;
- if (ctx->state.vg.filter_channel_mask & VG_ALPHA)
- blend.rt[0].colormask |= PIPE_MASK_A;
- blend.rt[0].blend_enable = 0;
- cso_set_blend(ctx->cso_context, &blend);
-}
-
-static void setup_constant_buffer(struct vg_context *ctx, const void *buffer,
- VGint param_bytes)
-{
- struct pipe_context *pipe = ctx->pipe;
- struct pipe_resource **cbuf = &ctx->filter.buffer;
-
- /* We always need to get a new buffer, to keep the drivers simple and
- * avoid gratuitous rendering synchronization. */
- pipe_resource_reference(cbuf, NULL);
-
- *cbuf = pipe_buffer_create(pipe->screen,
- PIPE_BIND_CONSTANT_BUFFER,
- param_bytes);
-
- if (*cbuf) {
- st_no_flush_pipe_buffer_write(ctx, *cbuf,
- 0, param_bytes, buffer);
- }
-
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
-}
-
-static void setup_samplers(struct vg_context *ctx, struct filter_info *info)
-{
- struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
- struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
- struct pipe_sampler_state sampler[3];
- int num_samplers = 0;
- int num_textures = 0;
-
- samplers[0] = NULL;
- samplers[1] = NULL;
- samplers[2] = NULL;
- samplers[3] = NULL;
- sampler_views[0] = NULL;
- sampler_views[1] = NULL;
- sampler_views[2] = NULL;
- sampler_views[3] = NULL;
-
- memset(&sampler[0], 0, sizeof(struct pipe_sampler_state));
- sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler[0].wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler[0].min_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
- sampler[0].mag_img_filter = PIPE_TEX_MIPFILTER_LINEAR;
- sampler[0].normalized_coords = 1;
-
- switch(info->tiling_mode) {
- case VG_TILE_FILL:
- sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
- sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
- memcpy(sampler[0].border_color,
- ctx->state.vg.tile_fill_color,
- sizeof(VGfloat) * 4);
- break;
- case VG_TILE_PAD:
- sampler[0].wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler[0].wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- break;
- case VG_TILE_REPEAT:
- sampler[0].wrap_s = PIPE_TEX_WRAP_REPEAT;
- sampler[0].wrap_t = PIPE_TEX_WRAP_REPEAT;
- break;
- case VG_TILE_REFLECT:
- sampler[0].wrap_s = PIPE_TEX_WRAP_MIRROR_REPEAT;
- sampler[0].wrap_t = PIPE_TEX_WRAP_MIRROR_REPEAT;
- break;
- default:
- debug_assert(!"Unknown tiling mode");
- }
-
- samplers[0] = &sampler[0];
- sampler_views[0] = info->src->sampler_view;
- ++num_samplers;
- ++num_textures;
-
- if (info->extra_texture_view) {
- memcpy(&sampler[1], &sampler[0], sizeof(struct pipe_sampler_state));
- samplers[1] = &sampler[1];
- sampler_views[1] = info->extra_texture_view;
- ++num_samplers;
- ++num_textures;
- }
-
-
- cso_set_samplers(ctx->cso_context, num_samplers, (const struct pipe_sampler_state **)samplers);
- cso_set_fragment_sampler_views(ctx->cso_context, num_textures, sampler_views);
-}
-
static struct vg_shader * setup_color_matrix(struct vg_context *ctx, void *user_data)
{
struct vg_shader *shader =
shader_create_from_text(ctx->pipe, color_matrix_asm, 200,
PIPE_SHADER_FRAGMENT);
- cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
return shader;
}
@@ -275,7 +132,6 @@ static struct vg_shader * setup_convolution(struct vg_context *ctx, void *user_d
shader = shader_create_from_text(ctx->pipe, buffer, 200,
PIPE_SHADER_FRAGMENT);
- cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
return shader;
}
@@ -285,7 +141,6 @@ static struct vg_shader * setup_lookup(struct vg_context *ctx, void *user_data)
shader_create_from_text(ctx->pipe, lookup_asm,
200, PIPE_SHADER_FRAGMENT);
- cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
return shader;
}
@@ -316,49 +171,68 @@ static struct vg_shader * setup_lookup_single(struct vg_context *ctx, void *user
shader = shader_create_from_text(ctx->pipe, buffer, 200,
PIPE_SHADER_FRAGMENT);
- cso_set_fragment_shader_handle(ctx->cso_context, shader->driver);
return shader;
}
static void execute_filter(struct vg_context *ctx,
struct filter_info *info)
{
- struct pipe_surface *dst_surf;
struct vg_shader *shader;
+ const struct pipe_sampler_state *samplers[2];
+ struct pipe_sampler_view *views[2];
+ struct pipe_sampler_state sampler;
+ uint tex_wrap;
+
+ memset(&sampler, 0, sizeof(sampler));
+ sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+ sampler.normalized_coords = 1;
+
+ switch (info->tiling_mode) {
+ case VG_TILE_FILL:
+ tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_BORDER;
+ /* copy border color */
+ memcpy(sampler.border_color, ctx->state.vg.tile_fill_color,
+ sizeof(sampler.border_color));
+ break;
+ case VG_TILE_PAD:
+ tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;;
+ break;
+ case VG_TILE_REPEAT:
+ tex_wrap = PIPE_TEX_WRAP_REPEAT;;
+ break;
+ case VG_TILE_REFLECT:
+ tex_wrap = PIPE_TEX_WRAP_MIRROR_REPEAT;
+ break;
+ default:
+ debug_assert(!"Unknown tiling mode");
+ tex_wrap = 0;
+ break;
+ }
+
+ sampler.wrap_s = tex_wrap;
+ sampler.wrap_t = tex_wrap;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+
+ samplers[0] = samplers[1] = &sampler;
+ views[0] = info->src->sampler_view;
+ views[1] = info->extra_texture_view;
- cso_save_framebuffer(ctx->cso_context);
- cso_save_fragment_shader(ctx->cso_context);
- cso_save_viewport(ctx->cso_context);
- cso_save_blend(ctx->cso_context);
- cso_save_samplers(ctx->cso_context);
- cso_save_fragment_sampler_views(ctx->cso_context);
-
- dst_surf = setup_framebuffer(info->dst);
- setup_viewport(info->dst);
- setup_blend();
- setup_constant_buffer(ctx, info->const_buffer, info->const_buffer_len);
shader = info->setup_shader(ctx, info->user_data);
- setup_samplers(ctx, info);
-
- renderer_draw_texture(ctx->renderer,
- info->src->sampler_view->texture,
- info->dst->x, info->dst->y,
- info->dst->x + info->dst->width,
- info->dst->y + info->dst->height,
- info->dst->x, info->dst->y,
- info->dst->x + info->dst->width,
- info->dst->y + info->dst->height);
-
- cso_restore_framebuffer(ctx->cso_context);
- cso_restore_fragment_shader(ctx->cso_context);
- cso_restore_viewport(ctx->cso_context);
- cso_restore_blend(ctx->cso_context);
- cso_restore_samplers(ctx->cso_context);
- cso_restore_fragment_sampler_views(ctx->cso_context);
- vg_shader_destroy(ctx, shader);
+ if (renderer_filter_begin(ctx->renderer,
+ info->dst->sampler_view->texture, VG_TRUE,
+ ctx->state.vg.filter_channel_mask,
+ samplers, views, (info->extra_texture_view) ? 2 : 1,
+ shader->driver, info->const_buffer, info->const_buffer_len)) {
+ renderer_filter(ctx->renderer,
+ info->dst->x, info->dst->y, info->dst->width, info->dst->height,
+ info->src->x, info->src->y, info->src->width, info->src->height);
+ renderer_filter_end(ctx->renderer);
+ }
- pipe_surface_reference(&dst_surf, NULL);
+ vg_shader_destroy(ctx, shader);
}
void vegaColorMatrix(VGImage dst, VGImage src,
@@ -796,6 +670,8 @@ void vegaLookupSingle(VGImage dst, VGImage src,
return;
}
+ vg_validate_state(ctx);
+
for (i = 0; i < 256; ++i) {
VGuint rgba = lookupTable[i];
VGubyte blue, green, red, alpha;
diff --git a/src/gallium/state_trackers/vega/api_images.c b/src/gallium/state_trackers/vega/api_images.c
index 7054d9bb7ed..ad95409cd00 100644
--- a/src/gallium/state_trackers/vega/api_images.c
+++ b/src/gallium/state_trackers/vega/api_images.c
@@ -37,6 +37,7 @@
#include "pipe/p_screen.h"
#include "util/u_inlines.h"
#include "util/u_tile.h"
+#include "util/u_math.h"
static INLINE VGboolean supported_image_format(VGImageFormat format)
{
@@ -302,7 +303,8 @@ void vegaDrawImage(VGImage image)
}
vg_validate_state(ctx);
- image_draw((struct vg_image*)image);
+ image_draw((struct vg_image*)image,
+ &ctx->state.vg.image_user_to_surface_matrix);
}
void vegaSetPixels(VGint dx, VGint dy,
@@ -398,11 +400,9 @@ void vegaReadPixels(void * data, VGint dataStride,
struct st_framebuffer *stfb = ctx->draw_buffer;
struct st_renderbuffer *strb = stfb->strb;
- struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
VGfloat *df = (VGfloat*)temp;
- VGint y = (fb->height - sy) - 1, yStep = -1;
VGint i;
VGubyte *dst = (VGubyte *)data;
VGint xoffset = 0, yoffset = 0;
@@ -430,18 +430,26 @@ void vegaReadPixels(void * data, VGint dataStride,
}
if (sy < 0) {
yoffset = -sy;
+ yoffset *= dataStride;
height += sy;
sy = 0;
- y = (fb->height - sy) - 1;
- yoffset *= dataStride;
+ }
+
+ if (sx + width > stfb->width || sy + height > stfb->height) {
+ width = stfb->width - sx;
+ height = stfb->height - sy;
+ /* nothing to read */
+ if (width <= 0 || height <= 0)
+ return;
}
{
+ VGint y = (stfb->height - sy) - 1, yStep = -1;
struct pipe_transfer *transfer;
- transfer = pipe_get_transfer(pipe, strb->texture, 0, 0, 0,
- PIPE_TRANSFER_READ,
- 0, 0, width, height);
+ transfer = pipe_get_transfer(pipe, strb->texture, 0, 0,
+ PIPE_TRANSFER_READ,
+ 0, 0, sx + width, stfb->height - sy);
/* Do a row at a time to flip image data vertically */
for (i = 0; i < height; i++) {
@@ -464,8 +472,8 @@ void vegaCopyPixels(VGint dx, VGint dy,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
- struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
- struct st_renderbuffer *strb = ctx->draw_buffer->strb;
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+ struct st_renderbuffer *strb = stfb->strb;
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
@@ -473,8 +481,8 @@ void vegaCopyPixels(VGint dx, VGint dy,
}
/* do nothing if we copy from outside the fb */
- if (dx >= (VGint)fb->width || dy >= (VGint)fb->height ||
- sx >= (VGint)fb->width || sy >= (VGint)fb->height)
+ if (dx >= (VGint)stfb->width || dy >= (VGint)stfb->height ||
+ sx >= (VGint)stfb->width || sy >= (VGint)stfb->height)
return;
vg_validate_state(ctx);
diff --git a/src/gallium/state_trackers/vega/api_masks.c b/src/gallium/state_trackers/vega/api_masks.c
index 189390ec2d3..beb15c33a59 100644
--- a/src/gallium/state_trackers/vega/api_masks.c
+++ b/src/gallium/state_trackers/vega/api_masks.c
@@ -28,6 +28,7 @@
#include "mask.h"
#include "api.h"
+#include "renderer.h"
#include "vg_context.h"
#include "pipe/p_context.h"
@@ -36,119 +37,6 @@
#include "util/u_pack_color.h"
#include "util/u_draw_quad.h"
-#define DISABLE_1_1_MASKING 1
-
-/**
- * Draw a screen-aligned quadrilateral.
- * Coords are window coords with y=0=bottom. These coords will be transformed
- * by the vertex shader and viewport transform.
- */
-static void
-draw_clear_quad(struct vg_context *st,
- float x0, float y0, float x1, float y1, float z,
- const VGfloat color[4])
-{
- struct pipe_context *pipe = st->pipe;
- struct pipe_resource *buf;
- VGuint i;
-
- /* positions */
- st->clear.vertices[0][0][0] = x0;
- st->clear.vertices[0][0][1] = y0;
-
- st->clear.vertices[1][0][0] = x1;
- st->clear.vertices[1][0][1] = y0;
-
- st->clear.vertices[2][0][0] = x1;
- st->clear.vertices[2][0][1] = y1;
-
- st->clear.vertices[3][0][0] = x0;
- st->clear.vertices[3][0][1] = y1;
-
- /* same for all verts: */
- for (i = 0; i < 4; i++) {
- st->clear.vertices[i][0][2] = z;
- st->clear.vertices[i][0][3] = 1.0;
- st->clear.vertices[i][1][0] = color[0];
- st->clear.vertices[i][1][1] = color[1];
- st->clear.vertices[i][1][2] = color[2];
- st->clear.vertices[i][1][3] = color[3];
- }
-
-
- /* put vertex data into vbuf */
- buf = pipe_user_buffer_create(pipe->screen,
- st->clear.vertices,
- sizeof(st->clear.vertices),
- PIPE_BIND_VERTEX_BUFFER);
-
-
- /* draw */
- if (buf) {
- cso_set_vertex_elements(st->cso_context, 2, st->velems);
-
- util_draw_vertex_buffer(pipe, buf, 0,
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 2); /* attribs/vert */
-
- pipe_resource_reference(&buf, NULL);
- }
-}
-
-/**
- * Do vgClear by drawing a quadrilateral.
- */
-static void
-clear_with_quad(struct vg_context *st, float x0, float y0,
- float width, float height, const VGfloat clear_color[4])
-{
- VGfloat x1, y1;
-
- vg_validate_state(st);
-
- x1 = x0 + width;
- y1 = y0 + height;
-
- /*
- printf("%s %f,%f %f,%f\n", __FUNCTION__,
- x0, y0,
- x1, y1);
- */
-
- cso_save_blend(st->cso_context);
- cso_save_rasterizer(st->cso_context);
- cso_save_fragment_shader(st->cso_context);
- cso_save_vertex_shader(st->cso_context);
-
- /* blend state: RGBA masking */
- {
- struct pipe_blend_state blend;
- memset(&blend, 0, sizeof(blend));
- blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].colormask = PIPE_MASK_RGBA;
- cso_set_blend(st->cso_context, &blend);
- }
-
- cso_set_rasterizer(st->cso_context, &st->clear.raster);
-
- cso_set_fragment_shader_handle(st->cso_context, st->clear.fs);
- cso_set_vertex_shader_handle(st->cso_context, vg_clear_vs(st));
-
- /* draw quad matching scissor rect (XXX verify coord round-off) */
- draw_clear_quad(st, x0, y0, x1, y1, 0, clear_color);
-
- /* Restore pipe state */
- cso_restore_blend(st->cso_context);
- cso_restore_rasterizer(st->cso_context);
- cso_restore_fragment_shader(st->cso_context);
- cso_restore_vertex_shader(st->cso_context);
-}
-
-
void vegaMask(VGHandle mask, VGMaskOperation operation,
VGint x, VGint y,
VGint width, VGint height)
@@ -176,12 +64,8 @@ void vegaMask(VGHandle mask, VGMaskOperation operation,
struct vg_image *image = (struct vg_image *)mask;
mask_using_image(image, operation, x, y, width, height);
} else if (vg_object_is_valid((void*)mask, VG_OBJECT_MASK)) {
-#if DISABLE_1_1_MASKING
- return;
-#else
struct vg_mask_layer *layer = (struct vg_mask_layer *)mask;
mask_using_layer(layer, operation, x, y, width, height);
-#endif
} else {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
}
@@ -191,7 +75,7 @@ void vegaClear(VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
- struct pipe_framebuffer_state *fb;
+ struct st_framebuffer *stfb = ctx->draw_buffer;
if (width <= 0 || height <= 0) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
@@ -208,14 +92,15 @@ void vegaClear(VGint x, VGint y,
ctx->state.vg.clear_color[3]);
#endif
- fb = &ctx->state.g3d.fb;
/* check for a whole surface clear */
if (!ctx->state.vg.scissoring &&
- (x == 0 && y == 0 && width == fb->width && height == fb->height)) {
+ (x == 0 && y == 0 && width == stfb->width && height == stfb->height)) {
ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_COLOR | PIPE_CLEAR_DEPTHSTENCIL,
ctx->state.vg.clear_color, 1., 0);
- } else {
- clear_with_quad(ctx, x, y, width, height, ctx->state.vg.clear_color);
+ } else if (renderer_clear_begin(ctx->renderer)) {
+ /* XXX verify coord round-off */
+ renderer_clear(ctx->renderer, x, y, width, height, ctx->state.vg.clear_color);
+ renderer_clear_end(ctx->renderer);
}
}
@@ -247,10 +132,6 @@ void vegaRenderToMask(VGPath path,
return;
}
-#if DISABLE_1_1_MASKING
- return;
-#endif
-
vg_validate_state(ctx);
mask_render_to((struct path *)path, paintModes, operation);
@@ -328,9 +209,8 @@ void vegaFillMaskLayer(VGMaskLayer maskLayer,
return;
}
-#if DISABLE_1_1_MASKING
- return;
-#endif
+ vg_validate_state(ctx);
+
mask_layer_fill(mask, x, y, width, height, value);
}
@@ -355,9 +235,7 @@ void vegaCopyMask(VGMaskLayer maskLayer,
return;
}
-#if DISABLE_1_1_MASKING
- return;
-#endif
+ vg_validate_state(ctx);
mask = (struct vg_mask_layer*)maskLayer;
mask_copy(mask, sx, sy, dx, dy, width, height);
diff --git a/src/gallium/state_trackers/vega/api_misc.c b/src/gallium/state_trackers/vega/api_misc.c
index e648549745b..9e2ab03e01a 100644
--- a/src/gallium/state_trackers/vega/api_misc.c
+++ b/src/gallium/state_trackers/vega/api_misc.c
@@ -63,8 +63,8 @@ const VGubyte *vegaGetString(VGStringID name)
{
struct vg_context *ctx = vg_current_context();
static const VGubyte *vendor = (VGubyte *)"Tungsten Graphics, Inc";
- static const VGubyte *renderer = (VGubyte *)"Vega OpenVG 1.0";
- static const VGubyte *version = (VGubyte *)"1.0";
+ static const VGubyte *renderer = (VGubyte *)"Vega OpenVG 1.1";
+ static const VGubyte *version = (VGubyte *)"1.1";
if (!ctx)
return NULL;
diff --git a/src/gallium/state_trackers/vega/api_params.c b/src/gallium/state_trackers/vega/api_params.c
index a10b009e631..a73b6c3effe 100644
--- a/src/gallium/state_trackers/vega/api_params.c
+++ b/src/gallium/state_trackers/vega/api_params.c
@@ -30,6 +30,7 @@
#include "paint.h"
#include "path.h"
#include "image.h"
+#include "text.h"
#include "matrix.h"
#include "api_consts.h"
#include "api.h"
@@ -174,6 +175,7 @@ void vegaSeti (VGParamType type, VGint value)
error = VG_ILLEGAL_ARGUMENT_ERROR;
else
state->image_mode = value;
+ break;
#ifdef OPENVG_VERSION_1_1
case VG_COLOR_TRANSFORM:
state->color_transform = value;
@@ -1500,7 +1502,8 @@ VGint vegaGetParameteri(VGHandle object,
#ifdef OPENVG_VERSION_1_1
case VG_FONT_NUM_GLYPHS: {
- return 1;
+ struct vg_font *font = (struct vg_font*)object;
+ return font_num_glyphs(font);
}
break;
#endif
diff --git a/src/gallium/state_trackers/vega/api_path.c b/src/gallium/state_trackers/vega/api_path.c
index f76adddb584..fe57b7671d9 100644
--- a/src/gallium/state_trackers/vega/api_path.c
+++ b/src/gallium/state_trackers/vega/api_path.c
@@ -479,6 +479,7 @@ void vegaDrawPath(VGPath path, VGbitfield paintModes)
if (path_is_empty((struct path*)path))
return;
- path_render((struct path*)path, paintModes);
+ path_render((struct path*)path, paintModes,
+ &ctx->state.vg.path_user_to_surface_matrix);
}
diff --git a/src/gallium/state_trackers/vega/api_text.c b/src/gallium/state_trackers/vega/api_text.c
index 2a62da0a1de..7c6b4794099 100644
--- a/src/gallium/state_trackers/vega/api_text.c
+++ b/src/gallium/state_trackers/vega/api_text.c
@@ -27,21 +27,15 @@
#include "VG/openvg.h"
#include "vg_context.h"
+#include "text.h"
+#include "api.h"
#include "util/u_memory.h"
#ifdef OPENVG_VERSION_1_1
-struct vg_font {
- struct vg_object base;
-
- VGint glyph_indices[200];
- VGint num_glyphs;
-};
-
VGFont vegaCreateFont(VGint glyphCapacityHint)
{
- struct vg_font *font = 0;
struct vg_context *ctx = vg_current_context();
if (glyphCapacityHint < 0) {
@@ -49,10 +43,7 @@ VGFont vegaCreateFont(VGint glyphCapacityHint)
return VG_INVALID_HANDLE;
}
- font = CALLOC_STRUCT(vg_font);
- vg_init_object(&font->base, ctx, VG_OBJECT_FONT);
- vg_context_add_object(ctx, VG_OBJECT_FONT, font);
- return (VGFont)font;
+ return (VGFont) font_create(glyphCapacityHint);
}
void vegaDestroyFont(VGFont f)
@@ -64,20 +55,23 @@ void vegaDestroyFont(VGFont f)
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
+ if (!vg_object_is_valid((void *) font, VG_OBJECT_FONT)) {
+ vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
+ return;
+ }
- vg_context_remove_object(ctx, VG_OBJECT_FONT, font);
- /*free(font);*/
+ font_destroy(font);
}
void vegaSetGlyphToPath(VGFont font,
VGuint glyphIndex,
VGPath path,
VGboolean isHinted,
- VGfloat glyphOrigin [2],
- VGfloat escapement[2])
+ const VGfloat glyphOrigin[2],
+ const VGfloat escapement[2])
{
struct vg_context *ctx = vg_current_context();
- struct vg_object *pathObj;
+ struct path *pathObj;
struct vg_font *f;
if (font == VG_INVALID_HANDLE ||
@@ -95,25 +89,22 @@ void vegaSetGlyphToPath(VGFont font,
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
- pathObj = (struct vg_object*)path;
- if (pathObj && pathObj->type != VG_OBJECT_PATH) {
- vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
- return;
- }
- f = (struct vg_font*)font;
- f->glyph_indices[f->num_glyphs] = glyphIndex;
- ++f->num_glyphs;
+ pathObj = (struct path*) path;
+ f = (struct vg_font*) font;
+
+ font_set_glyph_to_path(f, glyphIndex, pathObj,
+ isHinted, glyphOrigin, escapement);
}
void vegaSetGlyphToImage(VGFont font,
VGuint glyphIndex,
VGImage image,
- VGfloat glyphOrigin [2],
- VGfloat escapement[2])
+ const VGfloat glyphOrigin[2],
+ const VGfloat escapement[2])
{
struct vg_context *ctx = vg_current_context();
- struct vg_object *img_obj;
+ struct vg_image *img_obj;
struct vg_font *f;
if (font == VG_INVALID_HANDLE ||
@@ -131,26 +122,11 @@ void vegaSetGlyphToImage(VGFont font,
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
- img_obj = (struct vg_object*)image;
- if (img_obj && img_obj->type != VG_OBJECT_IMAGE) {
- vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
- return;
- }
+
+ img_obj = (struct vg_image*)image;
f = (struct vg_font*)font;
- f->glyph_indices[f->num_glyphs] = glyphIndex;
- ++f->num_glyphs;
-}
-static INLINE VGboolean font_contains_glyph(struct vg_font *font,
- VGuint glyph_index)
-{
- VGint i;
- for (i = 0; i < font->num_glyphs; ++i) {
- if (font->glyph_indices[i] == glyph_index) {
- return VG_TRUE;
- }
- }
- return VG_FALSE;
+ font_set_glyph_to_image(f, glyphIndex, img_obj, glyphOrigin, escapement);
}
void vegaClearGlyph(VGFont font,
@@ -158,30 +134,15 @@ void vegaClearGlyph(VGFont font,
{
struct vg_context *ctx = vg_current_context();
struct vg_font *f;
- VGint i;
if (font == VG_INVALID_HANDLE) {
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
- if (glyphIndex <= 0) {
- vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
- return;
- }
- f = (struct vg_font*)font;
- if (!font_contains_glyph(f, glyphIndex)) {
- vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
- return;
- }
- for (i = 0; i < f->num_glyphs; ++i) {
- if (f->glyph_indices[i] == glyphIndex) {
- /*FIXME*/
- f->glyph_indices[f->num_glyphs] = 0;
- --f->num_glyphs;
- return;
- }
- }
+ f = (struct vg_font*) font;
+
+ font_clear_glyph(f, glyphIndex);
}
void vegaDrawGlyph(VGFont font,
@@ -196,31 +157,24 @@ void vegaDrawGlyph(VGFont font,
vg_set_error(ctx, VG_BAD_HANDLE_ERROR);
return;
}
- if (glyphIndex <= 0) {
- vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
- return;
- }
if (paintModes & (~(VG_STROKE_PATH|VG_FILL_PATH))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
f = (struct vg_font*)font;
- if (!font_contains_glyph(f, glyphIndex)) {
- vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
- return;
- }
+
+ font_draw_glyph(f, glyphIndex, paintModes, allowAutoHinting);
}
void vegaDrawGlyphs(VGFont font,
VGint glyphCount,
- VGuint *glyphIndices,
- VGfloat *adjustments_x,
- VGfloat *adjustments_y,
+ const VGuint *glyphIndices,
+ const VGfloat *adjustments_x,
+ const VGfloat *adjustments_y,
VGbitfield paintModes,
VGboolean allowAutoHinting)
{
struct vg_context *ctx = vg_current_context();
- VGint i;
struct vg_font *f;
if (font == VG_INVALID_HANDLE) {
@@ -235,8 +189,8 @@ void vegaDrawGlyphs(VGFont font,
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
- if (!adjustments_x || !is_aligned(adjustments_x) ||
- !adjustments_y || !is_aligned(adjustments_y)) {
+ if ((adjustments_x && !is_aligned(adjustments_x)) ||
+ (adjustments_y && !is_aligned(adjustments_y))) {
vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
return;
}
@@ -246,13 +200,9 @@ void vegaDrawGlyphs(VGFont font,
}
f = (struct vg_font*)font;
- for (i = 0; i < glyphCount; ++i) {
- VGuint glyph_index = glyphIndices[i];
- if (!font_contains_glyph(f, glyph_index)) {
- vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
- return;
- }
- }
+
+ font_draw_glyphs(f, glyphCount, glyphIndices,
+ adjustments_x, adjustments_y, paintModes, allowAutoHinting);
}
-#endif
+#endif /* OPENVG_VERSION_1_1 */
diff --git a/src/gallium/state_trackers/vega/asm_fill.h b/src/gallium/state_trackers/vega/asm_fill.h
index 27773467fa8..77e6a14fe99 100644
--- a/src/gallium/state_trackers/vega/asm_fill.h
+++ b/src/gallium/state_trackers/vega/asm_fill.h
@@ -44,9 +44,31 @@ solid_fill( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
- ureg_MOV(ureg, *out, constant[0]);
+ ureg_MOV(ureg, *out, constant[2]);
}
+/**
+ * Perform frag-coord-to-paint-coord transform. The transformation is in
+ * CONST[4..6].
+ */
+#define PAINT_TRANSFORM \
+ ureg_MOV(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_XY), in[0]); \
+ ureg_MOV(ureg, \
+ ureg_writemask(temp[0], TGSI_WRITEMASK_Z), \
+ ureg_scalar(constant[3], TGSI_SWIZZLE_Y)); \
+ ureg_DP3(ureg, temp[1], constant[4], ureg_src(temp[0])); \
+ ureg_DP3(ureg, temp[2], constant[5], ureg_src(temp[0])); \
+ ureg_DP3(ureg, temp[3], constant[6], ureg_src(temp[0])); \
+ ureg_RCP(ureg, temp[3], ureg_src(temp[3])); \
+ ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3])); \
+ ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3])); \
+ ureg_MOV(ureg, \
+ ureg_writemask(temp[4], TGSI_WRITEMASK_X), \
+ ureg_src(temp[1])); \
+ ureg_MOV(ureg, \
+ ureg_writemask(temp[4], TGSI_WRITEMASK_Y), \
+ ureg_src(temp[2]));
+
static INLINE void
linear_grad( struct ureg_program *ureg,
struct ureg_dst *out,
@@ -55,30 +77,19 @@ linear_grad( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
+ PAINT_TRANSFORM
- ureg_MOV(ureg,
- ureg_writemask(temp[0], TGSI_WRITEMASK_XY),
- in[0]);
- ureg_MOV(ureg,
- ureg_writemask(temp[0], TGSI_WRITEMASK_Z),
- ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
- ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0]));
- ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0]));
- ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0]));
- ureg_RCP(ureg, temp[3], ureg_src(temp[3]));
- ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3]));
- ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3]));
- ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_X), ureg_src(temp[1]));
- ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_Y), ureg_src(temp[2]));
+ /* grad = DP2((x, y), CONST[2].xy) * CONST[2].z */
ureg_MUL(ureg, temp[0],
- ureg_scalar(constant[0], TGSI_SWIZZLE_Y),
+ ureg_scalar(constant[2], TGSI_SWIZZLE_Y),
ureg_scalar(ureg_src(temp[4]), TGSI_SWIZZLE_Y));
ureg_MAD(ureg, temp[1],
- ureg_scalar(constant[0], TGSI_SWIZZLE_X),
+ ureg_scalar(constant[2], TGSI_SWIZZLE_X),
ureg_scalar(ureg_src(temp[4]), TGSI_SWIZZLE_X),
ureg_src(temp[0]));
ureg_MUL(ureg, temp[2], ureg_src(temp[1]),
- ureg_scalar(constant[0], TGSI_SWIZZLE_Z));
+ ureg_scalar(constant[2], TGSI_SWIZZLE_Z));
+
ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[2]), sampler[0]);
}
@@ -90,52 +101,32 @@ radial_grad( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
-
- ureg_MOV(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_XY), in[0]);
- ureg_MOV(ureg,
- ureg_writemask(temp[0], TGSI_WRITEMASK_Z),
- ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
- ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0]));
- ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0]));
- ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0]));
+ PAINT_TRANSFORM
+
+ /*
+ * Calculate (sqrt(B^2 + AC) - B) / A, where
+ *
+ * A is CONST[2].z,
+ * B is DP2((x, y), CONST[2].xy), and
+ * C is DP2((x, y), (x, y)).
+ */
+
+ /* B and C */
+ ureg_DP2(ureg, temp[0], ureg_src(temp[4]), constant[2]);
+ ureg_DP2(ureg, temp[1], ureg_src(temp[4]), ureg_src(temp[4]));
+
+ /* the square root */
+ ureg_MUL(ureg, temp[2], ureg_src(temp[0]), ureg_src(temp[0]));
+ ureg_MAD(ureg, temp[3], ureg_src(temp[1]),
+ ureg_scalar(constant[2], TGSI_SWIZZLE_Z), ureg_src(temp[2]));
+ ureg_RSQ(ureg, temp[3], ureg_src(temp[3]));
ureg_RCP(ureg, temp[3], ureg_src(temp[3]));
- ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3]));
- ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3]));
- ureg_MOV(ureg, ureg_writemask(temp[5], TGSI_WRITEMASK_X), ureg_src(temp[1]));
- ureg_MOV(ureg, ureg_writemask(temp[5], TGSI_WRITEMASK_Y), ureg_src(temp[2]));
- ureg_MUL(ureg, temp[0], ureg_scalar(constant[0], TGSI_SWIZZLE_Y),
- ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y));
- ureg_MAD(ureg, temp[1],
- ureg_scalar(constant[0], TGSI_SWIZZLE_X),
- ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X), ureg_src(temp[0]));
- ureg_ADD(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[1]));
- ureg_MUL(ureg, temp[3],
- ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y),
- ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_Y));
- ureg_MAD(ureg, temp[4],
- ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X),
- ureg_scalar(ureg_src(temp[5]), TGSI_SWIZZLE_X),
- ureg_src(temp[3]));
- ureg_MOV(ureg, temp[4], ureg_negate(ureg_src(temp[4])));
- ureg_MUL(ureg, temp[2],
- ureg_scalar(constant[0], TGSI_SWIZZLE_Z),
- ureg_src(temp[4]));
- ureg_MUL(ureg, temp[0],
- ureg_scalar(constant[1], TGSI_SWIZZLE_W),
- ureg_src(temp[2]));
- ureg_MUL(ureg, temp[3], ureg_src(temp[1]), ureg_src(temp[1]));
-
- ureg_SUB(ureg, temp[2], ureg_src(temp[3]), ureg_src(temp[0]));
- ureg_RSQ(ureg, temp[2], ureg_abs(ureg_src(temp[2])));
- ureg_RCP(ureg, temp[2], ureg_src(temp[2]));
- ureg_SUB(ureg, temp[1], ureg_src(temp[2]), ureg_src(temp[1]));
- ureg_ADD(ureg, temp[0],
- ureg_scalar(constant[0], TGSI_SWIZZLE_Z),
- ureg_scalar(constant[0], TGSI_SWIZZLE_Z));
- ureg_RCP(ureg, temp[0], ureg_src(temp[0]));
- ureg_MUL(ureg, temp[2], ureg_src(temp[1]), ureg_src(temp[0]));
- ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[2]), sampler[0]);
+ ureg_SUB(ureg, temp[3], ureg_src(temp[3]), ureg_src(temp[0]));
+ ureg_RCP(ureg, temp[0], ureg_scalar(constant[2], TGSI_SWIZZLE_Z));
+ ureg_MUL(ureg, temp[0], ureg_src(temp[0]), ureg_src(temp[3]));
+
+ ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[0]), sampler[0]);
}
@@ -147,22 +138,11 @@ pattern( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
- ureg_MOV(ureg,
- ureg_writemask(temp[0], TGSI_WRITEMASK_XY),
- in[0]);
- ureg_MOV(ureg,
- ureg_writemask(temp[0], TGSI_WRITEMASK_Z),
- ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
- ureg_DP3(ureg, temp[1], constant[2], ureg_src(temp[0]));
- ureg_DP3(ureg, temp[2], constant[3], ureg_src(temp[0]));
- ureg_DP3(ureg, temp[3], constant[4], ureg_src(temp[0]));
- ureg_RCP(ureg, temp[3], ureg_src(temp[3]));
- ureg_MUL(ureg, temp[1], ureg_src(temp[1]), ureg_src(temp[3]));
- ureg_MUL(ureg, temp[2], ureg_src(temp[2]), ureg_src(temp[3]));
- ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_X), ureg_src(temp[1]));
- ureg_MOV(ureg, ureg_writemask(temp[4], TGSI_WRITEMASK_Y), ureg_src(temp[2]));
+ PAINT_TRANSFORM
+
+ /* (s, t) = (x / tex_width, y / tex_height) */
ureg_RCP(ureg, temp[0],
- ureg_swizzle(constant[1],
+ ureg_swizzle(constant[3],
TGSI_SWIZZLE_Z,
TGSI_SWIZZLE_W,
TGSI_SWIZZLE_Z,
@@ -176,22 +156,21 @@ pattern( struct ureg_program *ureg,
ureg_writemask(temp[1], TGSI_WRITEMASK_Y),
ureg_src(temp[1]),
ureg_src(temp[0]));
+
ureg_TEX(ureg, *out, TGSI_TEXTURE_2D, ureg_src(temp[1]), sampler[0]);
}
static INLINE void
-mask( struct ureg_program *ureg,
- struct ureg_dst *out,
- struct ureg_src *in,
- struct ureg_src *sampler,
- struct ureg_dst *temp,
- struct ureg_src *constant)
+paint_degenerate( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
{
- ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[1]);
- ureg_MUL(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_W),
- ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
- ureg_MOV(ureg, *out, ureg_src(temp[0]));
+ /* CONST[3].y is 1.0f */
+ ureg_MOV(ureg, temp[1], ureg_scalar(constant[3], TGSI_SWIZZLE_Y));
+ ureg_TEX(ureg, *out, TGSI_TEXTURE_1D, ureg_src(temp[1]), sampler[0]);
}
static INLINE void
@@ -202,7 +181,9 @@ image_normal( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
- ureg_TEX(ureg, *out, TGSI_TEXTURE_2D, in[1], sampler[3]);
+ /* store and pass image color in TEMP[1] */
+ ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[1], sampler[3]);
+ ureg_MOV(ureg, *out, ureg_src(temp[1]));
}
@@ -214,6 +195,7 @@ image_multiply( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
+ /* store and pass image color in TEMP[1] */
ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[1], sampler[3]);
ureg_MUL(ureg, *out, ureg_src(temp[0]), ureg_src(temp[1]));
}
@@ -227,43 +209,279 @@ image_stencil( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
+ /* store and pass image color in TEMP[1] */
ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[1], sampler[3]);
- ureg_MUL(ureg, *out, ureg_src(temp[0]), ureg_src(temp[1]));
+ ureg_MOV(ureg, *out, ureg_src(temp[0]));
+}
+
+static INLINE void
+color_transform( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ /* note that TEMP[1] may already be used for image color */
+
+ ureg_MAD(ureg, temp[2], ureg_src(temp[0]), constant[0], constant[1]);
+ /* clamp to [0.0f, 1.0f] */
+ ureg_CLAMP(ureg, temp[2],
+ ureg_src(temp[2]),
+ ureg_scalar(constant[3], TGSI_SWIZZLE_X),
+ ureg_scalar(constant[3], TGSI_SWIZZLE_Y));
+ ureg_MOV(ureg, *out, ureg_src(temp[2]));
+}
+
+static INLINE void
+alpha_normal( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ /* save per-channel alpha in TEMP[1] */
+ ureg_MOV(ureg, temp[1], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));
+
+ ureg_MOV(ureg, *out, ureg_src(temp[0]));
}
-#define EXTENDED_BLENDER_OVER_FUNC \
- ureg_SUB(ureg, temp[3], \
- ureg_scalar(constant[1], TGSI_SWIZZLE_Y), \
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W)); \
- ureg_SUB(ureg, temp[3], \
- ureg_scalar(constant[1], TGSI_SWIZZLE_Y), \
- ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W)); \
- ureg_MUL(ureg, temp[3], ureg_src(temp[0]), ureg_src(temp[3])); \
- ureg_MUL(ureg, temp[4], ureg_src(temp[1]), ureg_src(temp[4])); \
- ureg_ADD(ureg, temp[3], ureg_src(temp[3]), ureg_src(temp[4]));
+static INLINE void
+alpha_per_channel( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ /* save per-channel alpha in TEMP[1] */
+ ureg_MUL(ureg,
+ ureg_writemask(temp[1], TGSI_WRITEMASK_W),
+ ureg_src(temp[0]),
+ ureg_src(temp[1]));
+ ureg_MUL(ureg,
+ ureg_writemask(temp[1], TGSI_WRITEMASK_XYZ),
+ ureg_src(temp[1]),
+ ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+ /* update alpha */
+ ureg_MOV(ureg,
+ ureg_writemask(temp[0], TGSI_WRITEMASK_W),
+ ureg_src(temp[1]));
+ ureg_MOV(ureg, *out, ureg_src(temp[0]));
+}
+/**
+ * Premultiply src and dst.
+ */
static INLINE void
-blend_multiply( struct ureg_program *ureg,
+blend_premultiply( struct ureg_program *ureg,
+ struct ureg_src src,
+ struct ureg_src src_channel_alpha,
+ struct ureg_src dst)
+{
+ /* premultiply src */
+ ureg_MUL(ureg,
+ ureg_writemask(ureg_dst(src), TGSI_WRITEMASK_XYZ),
+ src,
+ src_channel_alpha);
+ /* premultiply dst */
+ ureg_MUL(ureg,
+ ureg_writemask(ureg_dst(dst), TGSI_WRITEMASK_XYZ),
+ dst,
+ ureg_scalar(dst, TGSI_SWIZZLE_W));
+}
+
+/**
+ * Unpremultiply src.
+ */
+static INLINE void
+blend_unpremultiply( struct ureg_program *ureg,
+ struct ureg_src src,
+ struct ureg_src one,
+ struct ureg_dst temp[1])
+{
+ /* replace 0.0f by 1.0f before calculating reciprocal */
+ ureg_CMP(ureg,
+ temp[0],
+ ureg_negate(ureg_scalar(src, TGSI_SWIZZLE_W)),
+ ureg_scalar(src, TGSI_SWIZZLE_W),
+ one);
+ ureg_RCP(ureg, temp[0], ureg_src(temp[0]));
+
+ ureg_MUL(ureg,
+ ureg_writemask(ureg_dst(src), TGSI_WRITEMASK_XYZ),
+ src,
+ ureg_src(temp[0]));
+}
+
+/**
+ * Emit instructions for the specified blend mode. Colors will be
+ * unpremultiplied. Two temporary registers are required.
+ *
+ * The output is written back to src.
+ */
+static INLINE void
+blend_generic(struct ureg_program *ureg,
+ VGBlendMode mode,
+ struct ureg_src src,
+ struct ureg_src src_channel_alpha,
+ struct ureg_src dst,
+ struct ureg_src one,
+ struct ureg_dst temp[2])
+{
+ struct ureg_dst out;
+
+ blend_premultiply(ureg, src, src_channel_alpha, dst);
+
+ /* blend in-place */
+ out = ureg_dst(src);
+
+ switch (mode) {
+ case VG_BLEND_SRC:
+ ureg_MOV(ureg, out, src);
+ break;
+ case VG_BLEND_SRC_OVER:
+ /* RGBA_out = RGBA_src + (1 - A_src) * RGBA_dst */
+ ureg_SUB(ureg, temp[0], one, src_channel_alpha);
+ ureg_MAD(ureg, out, ureg_src(temp[0]), dst, src);
+ break;
+ case VG_BLEND_DST_OVER:
+ /* RGBA_out = RGBA_dst + (1 - A_dst) * RGBA_src */
+ ureg_SUB(ureg, temp[0], one, ureg_scalar(dst, TGSI_SWIZZLE_W));
+ ureg_MAD(ureg, out, ureg_src(temp[0]), src, dst);
+ break;
+ case VG_BLEND_SRC_IN:
+ ureg_MUL(ureg, out, src, ureg_scalar(dst, TGSI_SWIZZLE_W));
+ break;
+ case VG_BLEND_DST_IN:
+ ureg_MUL(ureg, out, dst, src_channel_alpha);
+ break;
+ case VG_BLEND_MULTIPLY:
+ /*
+ * RGB_out = (1 - A_dst) * RGB_src + (1 - A_src) * RGB_dst +
+ * RGB_src * RGB_dst
+ */
+ ureg_MAD(ureg, temp[0],
+ ureg_scalar(dst, TGSI_SWIZZLE_W), ureg_negate(src), src);
+ ureg_MAD(ureg, temp[1],
+ src_channel_alpha, ureg_negate(dst), dst);
+ ureg_MAD(ureg, temp[0], src, dst, ureg_src(temp[0]));
+ ureg_ADD(ureg, out, ureg_src(temp[0]), ureg_src(temp[1]));
+ /* alpha is src over */
+ ureg_ADD(ureg, ureg_writemask(out, TGSI_WRITEMASK_W),
+ src, ureg_src(temp[1]));
+ break;
+ case VG_BLEND_SCREEN:
+ /* RGBA_out = RGBA_src + (1 - RGBA_src) * RGBA_dst */
+ ureg_SUB(ureg, temp[0], one, src);
+ ureg_MAD(ureg, out, ureg_src(temp[0]), dst, src);
+ break;
+ case VG_BLEND_DARKEN:
+ case VG_BLEND_LIGHTEN:
+ /* src over */
+ ureg_SUB(ureg, temp[0], one, src_channel_alpha);
+ ureg_MAD(ureg, temp[0], ureg_src(temp[0]), dst, src);
+ /* dst over */
+ ureg_SUB(ureg, temp[1], one, ureg_scalar(dst, TGSI_SWIZZLE_W));
+ ureg_MAD(ureg, temp[1], ureg_src(temp[1]), src, dst);
+ /* take min/max for colors */
+ if (mode == VG_BLEND_DARKEN) {
+ ureg_MIN(ureg, ureg_writemask(out, TGSI_WRITEMASK_XYZ),
+ ureg_src(temp[0]), ureg_src(temp[1]));
+ }
+ else {
+ ureg_MAX(ureg, ureg_writemask(out, TGSI_WRITEMASK_XYZ),
+ ureg_src(temp[0]), ureg_src(temp[1]));
+ }
+ break;
+ case VG_BLEND_ADDITIVE:
+ /* RGBA_out = RGBA_src + RGBA_dst */
+ ureg_ADD(ureg, temp[0], src, dst);
+ ureg_MIN(ureg, out, ureg_src(temp[0]), one);
+ break;
+ default:
+ assert(0);
+ break;
+ }
+
+ blend_unpremultiply(ureg, src, one, temp);
+}
+
+#define BLEND_GENERIC(mode) \
+ do { \
+ ureg_TEX(ureg, temp[2], TGSI_TEXTURE_2D, in[0], sampler[2]); \
+ blend_generic(ureg, (mode), ureg_src(temp[0]), ureg_src(temp[1]), \
+ ureg_src(temp[2]), \
+ ureg_scalar(constant[3], TGSI_SWIZZLE_Y), temp + 3); \
+ ureg_MOV(ureg, *out, ureg_src(temp[0])); \
+ } while (0)
+
+static INLINE void
+blend_src( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ BLEND_GENERIC(VG_BLEND_SRC);
+}
+
+static INLINE void
+blend_src_over( struct ureg_program *ureg,
struct ureg_dst *out,
struct ureg_src *in,
struct ureg_src *sampler,
struct ureg_dst *temp,
struct ureg_src *constant)
{
- ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
- EXTENDED_BLENDER_OVER_FUNC
- ureg_MUL(ureg, temp[4], ureg_src(temp[0]), ureg_src(temp[1]));
- ureg_ADD(ureg, temp[1], ureg_src(temp[4]), ureg_src(temp[3]));
+ BLEND_GENERIC(VG_BLEND_SRC_OVER);
+}
- ureg_MUL(ureg, temp[2], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
- ureg_ADD(ureg, temp[3], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
- ureg_SUB(ureg, ureg_writemask(temp[1], TGSI_WRITEMASK_W),
- ureg_src(temp[3]), ureg_src(temp[2]));
+static INLINE void
+blend_dst_over( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ BLEND_GENERIC(VG_BLEND_DST_OVER);
+}
- ureg_MOV(ureg, *out, ureg_src(temp[1]));
+static INLINE void
+blend_src_in( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ BLEND_GENERIC(VG_BLEND_SRC_IN);
+}
+
+static INLINE void
+blend_dst_in( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ BLEND_GENERIC(VG_BLEND_DST_IN);
+}
+
+static INLINE void
+blend_multiply( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ BLEND_GENERIC(VG_BLEND_MULTIPLY);
}
static INLINE void
@@ -274,10 +492,7 @@ blend_screen( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
- ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
- ureg_ADD(ureg, temp[3], ureg_src(temp[0]), ureg_src(temp[1]));
- ureg_MUL(ureg, temp[2], ureg_src(temp[0]), ureg_src(temp[1]));
- ureg_SUB(ureg, *out, ureg_src(temp[3]), ureg_src(temp[2]));
+ BLEND_GENERIC(VG_BLEND_SCREEN);
}
static INLINE void
@@ -288,23 +503,7 @@ blend_darken( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
- ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
- EXTENDED_BLENDER_OVER_FUNC
- ureg_MUL(ureg, temp[4], ureg_src(temp[0]),
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
- ureg_MUL(ureg, temp[5], ureg_src(temp[1]),
- ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));
- ureg_MIN(ureg, temp[4], ureg_src(temp[4]), ureg_src(temp[5]));
- ureg_ADD(ureg, temp[1], ureg_src(temp[3]), ureg_src(temp[4]));
-
- ureg_MUL(ureg, temp[2], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
- ureg_ADD(ureg, temp[3], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
- ureg_SUB(ureg, ureg_writemask(temp[1], TGSI_WRITEMASK_W),
- ureg_src(temp[3]), ureg_src(temp[2]));
-
- ureg_MOV(ureg, *out, ureg_src(temp[1]));
+ BLEND_GENERIC(VG_BLEND_DARKEN);
}
static INLINE void
@@ -315,23 +514,33 @@ blend_lighten( struct ureg_program *ureg,
struct ureg_dst *temp,
struct ureg_src *constant)
{
- ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[2]);
- EXTENDED_BLENDER_OVER_FUNC
- ureg_MUL(ureg, temp[4], ureg_src(temp[0]),
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
- ureg_MUL(ureg, temp[5], ureg_src(temp[1]),
- ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W));
- ureg_MAX(ureg, temp[4], ureg_src(temp[4]), ureg_src(temp[5]));
- ureg_ADD(ureg, temp[1], ureg_src(temp[3]), ureg_src(temp[4]));
+ BLEND_GENERIC(VG_BLEND_LIGHTEN);
+}
- ureg_MUL(ureg, temp[2], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
- ureg_ADD(ureg, temp[3], ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
- ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
- ureg_SUB(ureg, ureg_writemask(temp[1], TGSI_WRITEMASK_W),
- ureg_src(temp[3]), ureg_src(temp[2]));
+static INLINE void
+blend_additive( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ BLEND_GENERIC(VG_BLEND_ADDITIVE);
+}
- ureg_MOV(ureg, *out, ureg_src(temp[1]));
+static INLINE void
+mask( struct ureg_program *ureg,
+ struct ureg_dst *out,
+ struct ureg_src *in,
+ struct ureg_src *sampler,
+ struct ureg_dst *temp,
+ struct ureg_src *constant)
+{
+ ureg_TEX(ureg, temp[1], TGSI_TEXTURE_2D, in[0], sampler[1]);
+ ureg_MUL(ureg, ureg_writemask(temp[0], TGSI_WRITEMASK_W),
+ ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_W),
+ ureg_scalar(ureg_src(temp[1]), TGSI_SWIZZLE_W));
+ ureg_MOV(ureg, *out, ureg_src(temp[0]));
}
static INLINE void
@@ -369,11 +578,11 @@ color_bw( struct ureg_program *ureg,
struct ureg_src *constant)
{
ureg_ADD(ureg, temp[1],
- ureg_scalar(constant[1], TGSI_SWIZZLE_Y),
- ureg_scalar(constant[1], TGSI_SWIZZLE_Y));
+ ureg_scalar(constant[3], TGSI_SWIZZLE_Y),
+ ureg_scalar(constant[3], TGSI_SWIZZLE_Y));
ureg_RCP(ureg, temp[2], ureg_src(temp[1]));
ureg_ADD(ureg, temp[1],
- ureg_scalar(constant[1], TGSI_SWIZZLE_Y),
+ ureg_scalar(constant[3], TGSI_SWIZZLE_Y),
ureg_src(temp[2]));
ureg_ADD(ureg, ureg_writemask(temp[2], TGSI_WRITEMASK_X),
ureg_scalar(ureg_src(temp[0]), TGSI_SWIZZLE_X),
@@ -410,46 +619,75 @@ struct shader_asm_info {
};
-static const struct shader_asm_info shaders_asm[] = {
- /* fills */
+/* paint types */
+static const struct shader_asm_info shaders_paint_asm[] = {
{VEGA_SOLID_FILL_SHADER, solid_fill,
- VG_FALSE, 0, 1, 0, 0, 0, 0},
+ VG_FALSE, 2, 1, 0, 0, 0, 0},
{VEGA_LINEAR_GRADIENT_SHADER, linear_grad,
- VG_TRUE, 0, 5, 0, 1, 0, 5},
+ VG_TRUE, 2, 5, 0, 1, 0, 5},
{VEGA_RADIAL_GRADIENT_SHADER, radial_grad,
- VG_TRUE, 0, 5, 0, 1, 0, 6},
+ VG_TRUE, 2, 5, 0, 1, 0, 5},
{VEGA_PATTERN_SHADER, pattern,
- VG_TRUE, 1, 4, 0, 1, 0, 5},
+ VG_TRUE, 3, 4, 0, 1, 0, 5},
+ {VEGA_PAINT_DEGENERATE_SHADER, paint_degenerate,
+ VG_FALSE, 3, 1, 0, 1, 0, 2}
+};
- /* image draw modes */
+/* image draw modes */
+static const struct shader_asm_info shaders_image_asm[] = {
{VEGA_IMAGE_NORMAL_SHADER, image_normal,
- VG_TRUE, 0, 0, 3, 1, 0, 0},
+ VG_TRUE, 0, 0, 3, 1, 0, 2},
{VEGA_IMAGE_MULTIPLY_SHADER, image_multiply,
VG_TRUE, 0, 0, 3, 1, 0, 2},
{VEGA_IMAGE_STENCIL_SHADER, image_stencil,
- VG_TRUE, 0, 0, 3, 1, 0, 2},
+ VG_TRUE, 0, 0, 3, 1, 0, 2}
+};
+static const struct shader_asm_info shaders_color_transform_asm[] = {
+ {VEGA_COLOR_TRANSFORM_SHADER, color_transform,
+ VG_FALSE, 0, 4, 0, 0, 0, 3}
+};
+
+static const struct shader_asm_info shaders_alpha_asm[] = {
+ {VEGA_ALPHA_NORMAL_SHADER, alpha_normal,
+ VG_FALSE, 0, 0, 0, 0, 0, 2},
+ {VEGA_ALPHA_PER_CHANNEL_SHADER, alpha_per_channel,
+ VG_FALSE, 0, 0, 0, 0, 0, 2}
+};
+
+/* extra blend modes */
+static const struct shader_asm_info shaders_blend_asm[] = {
+#define BLEND_ASM_INFO(id, func) { (id), (func), VG_TRUE, 3, 1, 2, 1, 0, 5 }
+ BLEND_ASM_INFO(VEGA_BLEND_SRC_SHADER, blend_src),
+ BLEND_ASM_INFO(VEGA_BLEND_SRC_OVER_SHADER, blend_src_over),
+ BLEND_ASM_INFO(VEGA_BLEND_DST_OVER_SHADER, blend_dst_over),
+ BLEND_ASM_INFO(VEGA_BLEND_SRC_IN_SHADER, blend_src_in),
+ BLEND_ASM_INFO(VEGA_BLEND_DST_IN_SHADER, blend_dst_in),
+ BLEND_ASM_INFO(VEGA_BLEND_MULTIPLY_SHADER, blend_multiply),
+ BLEND_ASM_INFO(VEGA_BLEND_SCREEN_SHADER, blend_screen),
+ BLEND_ASM_INFO(VEGA_BLEND_DARKEN_SHADER, blend_darken),
+ BLEND_ASM_INFO(VEGA_BLEND_LIGHTEN_SHADER, blend_lighten),
+ BLEND_ASM_INFO(VEGA_BLEND_ADDITIVE_SHADER, blend_additive)
+#undef BLEND_ASM_INFO
+};
+
+static const struct shader_asm_info shaders_mask_asm[] = {
{VEGA_MASK_SHADER, mask,
- VG_TRUE, 0, 0, 1, 1, 0, 2},
-
- /* extra blend modes */
- {VEGA_BLEND_MULTIPLY_SHADER, blend_multiply,
- VG_TRUE, 1, 1, 2, 1, 0, 5},
- {VEGA_BLEND_SCREEN_SHADER, blend_screen,
- VG_TRUE, 0, 0, 2, 1, 0, 4},
- {VEGA_BLEND_DARKEN_SHADER, blend_darken,
- VG_TRUE, 1, 1, 2, 1, 0, 6},
- {VEGA_BLEND_LIGHTEN_SHADER, blend_lighten,
- VG_TRUE, 1, 1, 2, 1, 0, 6},
-
- /* premultiply */
+ VG_TRUE, 0, 0, 1, 1, 0, 2}
+};
+
+/* premultiply */
+static const struct shader_asm_info shaders_premultiply_asm[] = {
{VEGA_PREMULTIPLY_SHADER, premultiply,
VG_FALSE, 0, 0, 0, 0, 0, 1},
{VEGA_UNPREMULTIPLY_SHADER, unpremultiply,
VG_FALSE, 0, 0, 0, 0, 0, 1},
+};
- /* color transform to black and white */
+/* color transform to black and white */
+static const struct shader_asm_info shaders_bw_asm[] = {
{VEGA_BW_SHADER, color_bw,
- VG_FALSE, 1, 1, 0, 0, 0, 3},
+ VG_FALSE, 3, 1, 0, 0, 0, 3},
};
+
#endif
diff --git a/src/gallium/state_trackers/vega/asm_util.h b/src/gallium/state_trackers/vega/asm_util.h
index 903bfc88a4d..ae1842a62cd 100644
--- a/src/gallium/state_trackers/vega/asm_util.h
+++ b/src/gallium/state_trackers/vega/asm_util.h
@@ -27,16 +27,6 @@
#ifndef ASM_UTIL_H
#define ASM_UTIL_H
-
-static const char pass_through_depth_asm[] =
- "FRAG\n"
- "DCL IN[0], POSITION, LINEAR\n"
- "DCL OUT[0].z, POSITION, CONSTANT\n"
- "0: MOV OUT[0].z, IN[0].zzzz\n"
- "1: END\n";
-
-
-
/* μnew = μmask */
static const char set_mask_asm[] =
"FRAG\n"
@@ -92,45 +82,4 @@ static const char subtract_mask_asm[] =
"3: MUL OUT[0], TEMP[2].wwww, TEMP[0].wwww\n"
"4: END\n";
-
-static const char vs_plain_asm[] =
- "VERT\n"
- "DCL IN[0]\n"
- "DCL OUT[0], POSITION\n"
- "DCL TEMP[0]\n"
- "DCL CONST[0..1]\n"
- "0: MUL TEMP[0], IN[0], CONST[0]\n"
- "1: ADD TEMP[0], TEMP[0], CONST[1]\n"
- "2: MOV OUT[0], TEMP[0]\n"
- "3: END\n";
-
-static const char vs_clear_asm[] =
- "VERT\n"
- "DCL IN[0]\n"
- "DCL IN[1]\n"
- "DCL OUT[0], POSITION\n"
- "DCL OUT[1], COLOR\n"
- "DCL TEMP[0]\n"
- "DCL CONST[0..1]\n"
- "0: MUL TEMP[0], IN[0], CONST[0]\n"
- "1: ADD TEMP[0], TEMP[0], CONST[1]\n"
- "2: MOV OUT[0], TEMP[0]\n"
- "3: MOV OUT[1], IN[1]\n"
- "4: END\n";
-
-
-static const char vs_texture_asm[] =
- "VERT\n"
- "DCL IN[0]\n"
- "DCL IN[1]\n"
- "DCL OUT[0], POSITION\n"
- "DCL OUT[1], GENERIC\n"
- "DCL TEMP[0]\n"
- "DCL CONST[0..1]\n"
- "0: MUL TEMP[0], IN[0], CONST[0]\n"
- "1: ADD TEMP[0], TEMP[0], CONST[1]\n"
- "2: MOV OUT[0], TEMP[0]\n"
- "3: MOV OUT[1], IN[1]\n"
- "4: END\n";
-
#endif
diff --git a/src/gallium/state_trackers/vega/image.c b/src/gallium/state_trackers/vega/image.c
index 28bbe420a21..318ea94bdfb 100644
--- a/src/gallium/state_trackers/vega/image.c
+++ b/src/gallium/state_trackers/vega/image.c
@@ -42,6 +42,7 @@
#include "util/u_memory.h"
#include "util/u_math.h"
#include "util/u_sampler.h"
+#include "util/u_surface.h"
static enum pipe_format vg_format_to_pipe(VGImageFormat format)
{
@@ -77,33 +78,23 @@ static INLINE void vg_sync_size(VGfloat *src_loc, VGfloat *dst_loc)
dst_loc[3] = src_loc[3];
}
-
-static void vg_copy_texture(struct vg_context *ctx,
- struct pipe_resource *dst, VGint dx, VGint dy,
- struct pipe_sampler_view *src, VGint sx, VGint sy,
- VGint width, VGint height)
+static void vg_get_copy_coords(VGfloat *src_loc,
+ VGfloat src_width, VGfloat src_height,
+ VGfloat *dst_loc,
+ VGfloat dst_width, VGfloat dst_height)
{
- VGfloat dst_loc[4], src_loc[4];
VGfloat dst_bounds[4], src_bounds[4];
VGfloat src_shift[4], dst_shift[4], shift[4];
- dst_loc[0] = dx;
- dst_loc[1] = dy;
- dst_loc[2] = width;
- dst_loc[3] = height;
dst_bounds[0] = 0.f;
dst_bounds[1] = 0.f;
- dst_bounds[2] = dst->width0;
- dst_bounds[3] = dst->height0;
+ dst_bounds[2] = dst_width;
+ dst_bounds[3] = dst_height;
- src_loc[0] = sx;
- src_loc[1] = sy;
- src_loc[2] = width;
- src_loc[3] = height;
src_bounds[0] = 0.f;
src_bounds[1] = 0.f;
- src_bounds[2] = src->texture->width0;
- src_bounds[3] = src->texture->height0;
+ src_bounds[2] = src_width;
+ src_bounds[3] = src_height;
vg_bound_rect(src_loc, src_bounds, src_shift);
vg_bound_rect(dst_loc, dst_bounds, dst_shift);
@@ -121,22 +112,44 @@ static void vg_copy_texture(struct vg_context *ctx,
vg_shift_recty(dst_loc, dst_bounds, shift[1]);
vg_sync_size(src_loc, dst_loc);
+}
+
+static void vg_copy_texture(struct vg_context *ctx,
+ struct pipe_resource *dst, VGint dx, VGint dy,
+ struct pipe_sampler_view *src, VGint sx, VGint sy,
+ VGint width, VGint height)
+{
+ VGfloat dst_loc[4], src_loc[4];
+
+ dst_loc[0] = dx;
+ dst_loc[1] = dy;
+ dst_loc[2] = width;
+ dst_loc[3] = height;
+
+ src_loc[0] = sx;
+ src_loc[1] = sy;
+ src_loc[2] = width;
+ src_loc[3] = height;
+
+ vg_get_copy_coords(src_loc, src->texture->width0, src->texture->height0,
+ dst_loc, dst->width0, dst->height0);
if (src_loc[2] >= 0 && src_loc[3] >= 0 &&
dst_loc[2] >= 0 && dst_loc[3] >= 0) {
- renderer_copy_texture(ctx->renderer,
- src,
- src_loc[0],
- src_loc[1] + src_loc[3],
- src_loc[0] + src_loc[2],
- src_loc[1],
- dst,
- dst_loc[0],
- dst_loc[1] + dst_loc[3],
- dst_loc[0] + dst_loc[2],
- dst_loc[1]);
- }
+ struct pipe_surface *surf, surf_tmpl;
+
+ /* get the destination surface */
+ u_surface_default_template(&surf_tmpl, dst, PIPE_BIND_RENDER_TARGET);
+ surf = ctx->pipe->create_surface(ctx->pipe, dst, &surf_tmpl);
+ if (surf && renderer_copy_begin(ctx->renderer, surf, VG_TRUE, src)) {
+ renderer_copy(ctx->renderer,
+ dst_loc[0], dst_loc[1], dst_loc[2], dst_loc[3],
+ src_loc[0], src_loc[1], src_loc[2], src_loc[3]);
+ renderer_copy_end(ctx->renderer);
+ }
+ pipe_surface_reference(&surf, NULL);
+ }
}
void vg_copy_surface(struct vg_context *ctx,
@@ -145,43 +158,19 @@ void vg_copy_surface(struct vg_context *ctx,
VGint width, VGint height)
{
VGfloat dst_loc[4], src_loc[4];
- VGfloat dst_bounds[4], src_bounds[4];
- VGfloat src_shift[4], dst_shift[4], shift[4];
dst_loc[0] = dx;
dst_loc[1] = dy;
dst_loc[2] = width;
dst_loc[3] = height;
- dst_bounds[0] = 0.f;
- dst_bounds[1] = 0.f;
- dst_bounds[2] = dst->width;
- dst_bounds[3] = dst->height;
src_loc[0] = sx;
src_loc[1] = sy;
src_loc[2] = width;
src_loc[3] = height;
- src_bounds[0] = 0.f;
- src_bounds[1] = 0.f;
- src_bounds[2] = src->width;
- src_bounds[3] = src->height;
-
- vg_bound_rect(src_loc, src_bounds, src_shift);
- vg_bound_rect(dst_loc, dst_bounds, dst_shift);
- shift[0] = src_shift[0] - dst_shift[0];
- shift[1] = src_shift[1] - dst_shift[1];
-
- if (shift[0] < 0)
- vg_shift_rectx(src_loc, src_bounds, -shift[0]);
- else
- vg_shift_rectx(dst_loc, dst_bounds, shift[0]);
-
- if (shift[1] < 0)
- vg_shift_recty(src_loc, src_bounds, -shift[1]);
- else
- vg_shift_recty(dst_loc, dst_bounds, shift[1]);
- vg_sync_size(src_loc, dst_loc);
+ vg_get_copy_coords(src_loc, src->width, src->height,
+ dst_loc, dst->width, dst->height);
if (src_loc[2] > 0 && src_loc[3] > 0 &&
dst_loc[2] > 0 && dst_loc[3] > 0) {
@@ -277,6 +266,7 @@ struct vg_image * image_create(VGImageFormat format,
pt.width0 = width;
pt.height0 = height;
pt.depth0 = 1;
+ pt.array_size = 1;
pt.bind = PIPE_BIND_SAMPLER_VIEW;
newtex = screen->resource_create(screen, &pt);
@@ -284,6 +274,13 @@ struct vg_image * image_create(VGImageFormat format,
debug_assert(newtex);
u_sampler_view_default_template(&view_templ, newtex, newtex->format);
+ /* R, G, and B are treated as 1.0 for alpha-only formats in OpenVG */
+ if (newtex->format == PIPE_FORMAT_A8_UNORM) {
+ view_templ.swizzle_r = PIPE_SWIZZLE_ONE;
+ view_templ.swizzle_g = PIPE_SWIZZLE_ONE;
+ view_templ.swizzle_b = PIPE_SWIZZLE_ONE;
+ }
+
view = pipe->create_sampler_view(pipe, newtex, &view_templ);
/* want the texture to go away if the view is freed */
pipe_resource_reference(&newtex, NULL);
@@ -420,7 +417,7 @@ void image_sub_data(struct vg_image *image,
{ /* upload color_data */
struct pipe_transfer *transfer = pipe_get_transfer(
- pipe, texture, 0, 0, 0,
+ pipe, texture, 0, 0,
PIPE_TRANSFER_WRITE, 0, 0, texture->width0, texture->height0);
src += (dataStride * yoffset);
for (i = 0; i < height; i++) {
@@ -451,11 +448,11 @@ void image_get_sub_data(struct vg_image * image,
{
struct pipe_transfer *transfer =
pipe_get_transfer(pipe,
- image->sampler_view->texture, 0, 0, 0,
- PIPE_TRANSFER_READ,
- 0, 0,
- image->x + image->width,
- image->y + image->height);
+ image->sampler_view->texture, 0, 0,
+ PIPE_TRANSFER_READ,
+ 0, 0,
+ image->x + image->width,
+ image->y + image->height);
/* Do a row at a time to flip image data vertically */
for (i = 0; i < height; i++) {
#if 0
@@ -525,14 +522,20 @@ void image_copy(struct vg_image *dst, VGint dx, VGint dy,
src->sampler_view, src->x + sx, src->y + sy, width, height);
}
-void image_draw(struct vg_image *img)
+void image_draw(struct vg_image *img, struct matrix *matrix)
{
struct vg_context *ctx = vg_current_context();
+ struct matrix paint_matrix;
VGfloat x1, y1;
VGfloat x2, y2;
VGfloat x3, y3;
VGfloat x4, y4;
- struct matrix *matrix;
+
+ if (!vg_get_paint_matrix(ctx,
+ &ctx->state.vg.fill_paint_to_user_matrix,
+ matrix,
+ &paint_matrix))
+ return;
x1 = 0;
y1 = 0;
@@ -543,15 +546,10 @@ void image_draw(struct vg_image *img)
x4 = 0;
y4 = img->height;
- matrix = &ctx->state.vg.image_user_to_surface_matrix;
-
- matrix_map_point(matrix, x1, y1, &x1, &y1);
- matrix_map_point(matrix, x2, y2, &x2, &y2);
- matrix_map_point(matrix, x3, y3, &x3, &y3);
- matrix_map_point(matrix, x4, y4, &x4, &y4);
-
+ shader_set_surface_matrix(ctx->shader, matrix);
shader_set_drawing_image(ctx->shader, VG_TRUE);
shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
+ shader_set_paint_matrix(ctx->shader, &paint_matrix);
shader_set_image(ctx->shader, img);
shader_bind(ctx->shader);
@@ -566,20 +564,21 @@ void image_set_pixels(VGint dx, VGint dy,
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
- struct pipe_surface *surf;
+ struct pipe_surface *surf, surf_tmpl;
struct st_renderbuffer *strb = ctx->draw_buffer->strb;
/* make sure rendering has completed */
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
- surf = screen->get_tex_surface(screen, image_texture(src), 0, 0, 0,
- 0 /* no bind flags as surf isn't actually used??? */);
+ memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+ u_surface_default_template(&surf_tmpl, image_texture(src),
+ 0 /* no bind flag - not a surface*/);
+ surf = pipe->create_surface(pipe, image_texture(src), &surf_tmpl);
vg_copy_surface(ctx, strb->surface, dx, dy,
surf, sx+src->x, sy+src->y, width, height);
- screen->tex_surface_destroy(surf);
+ pipe->surface_destroy(pipe, surf);
}
void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
@@ -588,8 +587,7 @@ void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
- struct pipe_surface *surf;
+ struct pipe_surface *surf, surf_tmpl;
struct st_renderbuffer *strb = ctx->draw_buffer->strb;
/* flip the y coordinates */
@@ -598,8 +596,10 @@ void image_get_pixels(struct vg_image *dst, VGint dx, VGint dy,
/* make sure rendering has completed */
pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
- surf = screen->get_tex_surface(screen, image_texture(dst), 0, 0, 0,
- 0 /* no bind flags as surf isn't actually used??? */);
+ memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+ u_surface_default_template(&surf_tmpl, image_texture(dst),
+ PIPE_BIND_RENDER_TARGET);
+ surf = pipe->create_surface(pipe, image_texture(dst), &surf_tmpl);
vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy,
strb->surface, sx, sy, width, height);
diff --git a/src/gallium/state_trackers/vega/image.h b/src/gallium/state_trackers/vega/image.h
index a990c9c5873..391c0485948 100644
--- a/src/gallium/state_trackers/vega/image.h
+++ b/src/gallium/state_trackers/vega/image.h
@@ -79,7 +79,7 @@ void image_copy(struct vg_image *dst, VGint dx, VGint dy,
VGint width, VGint height,
VGboolean dither);
-void image_draw(struct vg_image *img);
+void image_draw(struct vg_image *img, struct matrix *matrix);
void image_set_pixels(VGint dx, VGint dy,
struct vg_image *src, VGint sx, VGint sy,
diff --git a/src/gallium/state_trackers/vega/mask.c b/src/gallium/state_trackers/vega/mask.c
index ef28ebd740c..dfd0600e444 100644
--- a/src/gallium/state_trackers/vega/mask.c
+++ b/src/gallium/state_trackers/vega/mask.c
@@ -31,13 +31,14 @@
#include "shaders_cache.h"
#include "renderer.h"
#include "asm_util.h"
-#include "st_inlines.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "util/u_inlines.h"
#include "util/u_format.h"
#include "util/u_memory.h"
+#include "util/u_surface.h"
+#include "util/u_sampler.h"
struct vg_mask_layer {
struct vg_object base;
@@ -48,17 +49,6 @@ struct vg_mask_layer {
struct pipe_sampler_view *sampler_view;
};
-static INLINE struct pipe_surface *
-alpha_mask_surface(struct vg_context *ctx, int usage)
-{
- struct pipe_screen *screen = ctx->pipe->screen;
- struct st_framebuffer *stfb = ctx->draw_buffer;
- return screen->get_tex_surface(screen,
- stfb->alpha_mask_view->texture,
- 0, 0, 0,
- usage);
-}
-
static INLINE VGboolean
intersect_rectangles(VGint dwidth, VGint dheight,
VGint swidth, VGint sheight,
@@ -110,15 +100,13 @@ static void read_alpha_mask(void * data, VGint dataStride,
{
struct vg_context *ctx = vg_current_context();
struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
struct st_framebuffer *stfb = ctx->draw_buffer;
struct st_renderbuffer *strb = stfb->alpha_mask;
- struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
VGfloat *df = (VGfloat*)temp;
- VGint y = (fb->height - sy) - 1, yStep = -1;
+ VGint y = (stfb->height - sy) - 1, yStep = -1;
VGint i;
VGubyte *dst = (VGubyte *)data;
VGint xoffset = 0, yoffset = 0;
@@ -135,15 +123,15 @@ static void read_alpha_mask(void * data, VGint dataStride,
yoffset = -sy;
height += sy;
sy = 0;
- y = (fb->height - sy) - 1;
+ y = (stfb->height - sy) - 1;
yoffset *= dataStride;
}
{
struct pipe_surface *surf;
- surf = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
- PIPE_BIND_TRANSFER_READ);
+ surf = pipe->create_surface(pipe, strb->texture, 0, 0, 0,
+ PIPE_BIND_TRANSFER_READ);
/* Do a row at a time to flip image data vertically */
for (i = 0; i < height; i++) {
@@ -164,23 +152,23 @@ static void read_alpha_mask(void * data, VGint dataStride,
void save_alpha_to_file(const char *filename)
{
struct vg_context *ctx = vg_current_context();
- struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
+ struct st_framebuffer *stfb = ctx->draw_buffer;
VGint *data;
int i, j;
- data = malloc(sizeof(int) * fb->width * fb->height);
- read_alpha_mask(data, fb->width * sizeof(int),
+ data = malloc(sizeof(int) * stfb->width * stfb->height);
+ read_alpha_mask(data, stfb->width * sizeof(int),
VG_sRGBA_8888,
- 0, 0, fb->width, fb->height);
+ 0, 0, stfb->width, stfb->height);
fprintf(stderr, "/*---------- start */\n");
fprintf(stderr, "const int image_width = %d;\n",
- fb->width);
+ stfb->width);
fprintf(stderr, "const int image_height = %d;\n",
- fb->height);
+ stfb->height);
fprintf(stderr, "const int image_data = {\n");
- for (i = 0; i < fb->height; ++i) {
- for (j = 0; j < fb->width; ++j) {
- int rgba = data[i * fb->height + j];
+ for (i = 0; i < stfb->height; ++i) {
+ for (j = 0; j < stfb->width; ++j) {
+ int rgba = data[i * stfb->height + j];
int argb = 0;
argb = (rgba >> 8);
argb |= ((rgba & 0xff) << 24);
@@ -193,49 +181,12 @@ void save_alpha_to_file(const char *filename)
}
#endif
-static void setup_mask_framebuffer(struct pipe_surface *surf,
- VGint surf_width, VGint surf_height)
-{
- struct vg_context *ctx = vg_current_context();
- struct pipe_framebuffer_state fb;
-
- memset(&fb, 0, sizeof(fb));
- fb.width = surf_width;
- fb.height = surf_height;
- fb.nr_cbufs = 1;
- fb.cbufs[0] = surf;
- {
- VGint i;
- for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
- fb.cbufs[i] = 0;
- }
- cso_set_framebuffer(ctx->cso_context, &fb);
-}
-
-
-/* setup shader constants */
-static void setup_mask_operation(VGMaskOperation operation)
+/* setup mask shader */
+static void *setup_mask_operation(VGMaskOperation operation)
{
struct vg_context *ctx = vg_current_context();
- struct pipe_resource **cbuf = &ctx->mask.cbuf;
- const VGint param_bytes = 4 * sizeof(VGfloat);
- const VGfloat ones[4] = {1.f, 1.f, 1.f, 1.f};
void *shader = 0;
- /* We always need to get a new buffer, to keep the drivers simple and
- * avoid gratuitous rendering synchronization.
- */
- pipe_resource_reference(cbuf, NULL);
-
- *cbuf = pipe_buffer_create(ctx->pipe->screen,
- PIPE_BIND_CONSTANT_BUFFER,
- param_bytes);
- if (*cbuf) {
- st_no_flush_pipe_buffer_write(ctx, *cbuf,
- 0, param_bytes, ones);
- }
-
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
switch (operation) {
case VG_UNION_MASK: {
if (!ctx->mask.union_fs) {
@@ -281,94 +232,21 @@ static void setup_mask_operation(VGMaskOperation operation)
assert(0);
break;
}
- cso_set_fragment_shader_handle(ctx->cso_context, shader);
-}
-
-static void setup_mask_samplers(struct pipe_sampler_view *umask)
-{
- struct vg_context *ctx = vg_current_context();
- struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
- struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
- struct st_framebuffer *fb_buffers = ctx->draw_buffer;
- struct pipe_sampler_view *uprev = NULL;
- struct pipe_sampler_state sampler;
-
- uprev = fb_buffers->blend_texture_view;
- sampler = ctx->mask.sampler;
- sampler.normalized_coords = 1;
-
- samplers[0] = NULL;
- samplers[1] = NULL;
- sampler_views[0] = NULL;
- sampler_views[1] = NULL;
-
- samplers[0] = &sampler;
- samplers[1] = &ctx->mask.sampler;
-
- sampler_views[0] = umask;
- sampler_views[1] = uprev;
-
- cso_set_samplers(ctx->cso_context, 2,
- (const struct pipe_sampler_state **)samplers);
- cso_set_fragment_sampler_views(ctx->cso_context, 2, sampler_views);
-}
-
-
-/* setup shader constants */
-static void setup_mask_fill(const VGfloat color[4])
-{
- struct vg_context *ctx = vg_current_context();
- struct pipe_resource **cbuf = &ctx->mask.cbuf;
- const VGint param_bytes = 4 * sizeof(VGfloat);
-
- /* We always need to get a new buffer, to keep the drivers simple and
- * avoid gratuitous rendering synchronization.
- */
- pipe_resource_reference(cbuf, NULL);
-
- *cbuf = pipe_buffer_create(ctx->pipe->screen,
- PIPE_BIND_CONSTANT_BUFFER,
- param_bytes);
- if (*cbuf) {
- st_no_flush_pipe_buffer_write(ctx, *cbuf, 0, param_bytes, color);
- }
-
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
- cso_set_fragment_shader_handle(ctx->cso_context,
- shaders_cache_fill(ctx->sc,
- VEGA_SOLID_FILL_SHADER));
-}
-
-static void setup_mask_viewport()
-{
- struct vg_context *ctx = vg_current_context();
- vg_set_viewport(ctx, VEGA_Y0_TOP);
-}
-
-static void setup_mask_blend()
-{
- struct vg_context *ctx = vg_current_context();
-
- struct pipe_blend_state blend;
- memset(&blend, 0, sizeof(struct pipe_blend_state));
- blend.rt[0].blend_enable = 0;
- blend.rt[0].colormask = PIPE_MASK_RGBA;
- blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
-
- cso_set_blend(ctx->cso_context, &blend);
+ return shader;
}
-
-static void surface_fill(struct pipe_surface *surf,
- int surf_width, int surf_height,
- int x, int y, int width, int height,
- const VGfloat color[4])
+static void mask_resource_fill(struct pipe_resource *dst,
+ int x, int y, int width, int height,
+ VGfloat coverage)
{
struct vg_context *ctx = vg_current_context();
+ VGfloat fs_consts[12] = {
+ 0.0f, 0.0f, 0.0f, 0.0f, /* not used */
+ 0.0f, 0.0f, 0.0f, 0.0f, /* not used */
+ 0.0f, 0.0f, 0.0f, coverage /* color */
+ };
+ void *fs;
if (x < 0) {
width += x;
@@ -379,50 +257,38 @@ static void surface_fill(struct pipe_surface *surf,
y = 0;
}
- cso_save_framebuffer(ctx->cso_context);
- cso_save_blend(ctx->cso_context);
- cso_save_fragment_shader(ctx->cso_context);
- cso_save_viewport(ctx->cso_context);
-
- setup_mask_blend();
- setup_mask_fill(color);
- setup_mask_framebuffer(surf, surf_width, surf_height);
- setup_mask_viewport();
+ fs = shaders_cache_fill(ctx->sc, VEGA_SOLID_FILL_SHADER);
- renderer_draw_quad(ctx->renderer, x, y,
- x + width, y + height, 0.0f/*depth should be disabled*/);
-
-
- /* make sure rendering has completed */
- ctx->pipe->flush(ctx->pipe,
- PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_FRAME,
- NULL);
+ if (renderer_filter_begin(ctx->renderer, dst, VG_FALSE, ~0,
+ NULL, NULL, 0, fs, (const void *) fs_consts, sizeof(fs_consts))) {
+ renderer_filter(ctx->renderer, x, y, width, height, 0, 0, 0, 0);
+ renderer_filter_end(ctx->renderer);
+ }
#if DEBUG_MASKS
save_alpha_to_file(0);
#endif
-
- cso_restore_blend(ctx->cso_context);
- cso_restore_framebuffer(ctx->cso_context);
- cso_restore_fragment_shader(ctx->cso_context);
- cso_restore_viewport(ctx->cso_context);
}
static void mask_using_texture(struct pipe_sampler_view *sampler_view,
+ VGboolean is_layer,
VGMaskOperation operation,
VGint x, VGint y,
VGint width, VGint height)
{
struct vg_context *ctx = vg_current_context();
+ struct pipe_sampler_view *dst_view = vg_get_surface_mask(ctx);
+ struct pipe_resource *dst = dst_view->texture;
struct pipe_resource *texture = sampler_view->texture;
- struct pipe_surface *surface =
- alpha_mask_surface(ctx, PIPE_BIND_RENDER_TARGET);
+ const struct pipe_sampler_state *samplers[2];
+ struct pipe_sampler_view *views[2];
+ struct pipe_sampler_state sampler;
VGint offsets[4], loc[4];
+ const VGfloat ones[4] = {1.f, 1.f, 1.f, 1.f};
+ void *fs;
- if (!surface)
- return;
- if (!intersect_rectangles(surface->width, surface->height,
+ if (!intersect_rectangles(dst->width0, dst->height0,
texture->width0, texture->height0,
x, y, width, height,
offsets, loc))
@@ -434,38 +300,30 @@ static void mask_using_texture(struct pipe_sampler_view *sampler_view,
loc[1], loc[2], loc[3]);
#endif
+
+ sampler = ctx->mask.sampler;
+ sampler.normalized_coords = 1;
+ samplers[0] = &sampler;
+ views[0] = sampler_view;
+
/* prepare our blend surface */
- vg_prepare_blend_surface_from_mask(ctx);
-
- cso_save_samplers(ctx->cso_context);
- cso_save_fragment_sampler_views(ctx->cso_context);
- cso_save_framebuffer(ctx->cso_context);
- cso_save_blend(ctx->cso_context);
- cso_save_fragment_shader(ctx->cso_context);
- cso_save_viewport(ctx->cso_context);
-
- setup_mask_samplers(sampler_view);
- setup_mask_blend();
- setup_mask_operation(operation);
- setup_mask_framebuffer(surface, surface->width, surface->height);
- setup_mask_viewport();
-
- /* render the quad to propagate the rendering from stencil */
- renderer_draw_texture(ctx->renderer, texture,
- offsets[0], offsets[1],
- offsets[0] + offsets[2], offsets[1] + offsets[3],
- loc[0], loc[1], loc[0] + loc[2], loc[1] + loc[3]);
+ samplers[1] = &ctx->mask.sampler;
+ views[1] = vg_prepare_blend_surface_from_mask(ctx);
- /* make sure rendering has completed */
- ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
- cso_restore_blend(ctx->cso_context);
- cso_restore_framebuffer(ctx->cso_context);
- cso_restore_fragment_shader(ctx->cso_context);
- cso_restore_samplers(ctx->cso_context);
- cso_restore_fragment_sampler_views(ctx->cso_context);
- cso_restore_viewport(ctx->cso_context);
-
- pipe_surface_reference(&surface, NULL);
+ fs = setup_mask_operation(operation);
+
+ if (renderer_filter_begin(ctx->renderer, dst, VG_FALSE,
+ ~0, samplers, views, 2, fs, (const void *) ones, sizeof(ones))) {
+ /* layer should be flipped when used as a texture */
+ if (is_layer) {
+ offsets[1] += offsets[3];
+ offsets[3] = -offsets[3];
+ }
+ renderer_filter(ctx->renderer,
+ loc[0], loc[1], loc[2], loc[3],
+ offsets[0], offsets[1], offsets[2], offsets[3]);
+ renderer_filter_end(ctx->renderer);
+ }
}
@@ -496,8 +354,8 @@ struct vg_mask_layer * mask_layer_create(VGint width, VGint height)
pt.width0 = width;
pt.height0 = height;
pt.depth0 = 1;
+ pt.array_size = 1;
pt.bind = PIPE_BIND_SAMPLER_VIEW;
- pt.compressed = 0;
texture = screen->resource_create(screen, &pt);
@@ -519,7 +377,7 @@ void mask_layer_destroy(struct vg_mask_layer *layer)
struct vg_context *ctx = vg_current_context();
vg_context_remove_object(ctx, VG_OBJECT_MASK, layer);
- pipe_resource_release(&layer->texture);
+ pipe_sampler_view_reference(&layer->sampler_view, NULL);
FREE(layer);
}
@@ -528,22 +386,12 @@ void mask_layer_fill(struct vg_mask_layer *layer,
VGint width, VGint height,
VGfloat value)
{
- struct vg_context *ctx = vg_current_context();
VGfloat alpha_color[4] = {0, 0, 0, 0};
- struct pipe_surface *surface;
alpha_color[3] = value;
- surface = ctx->pipe->screen->get_tex_surface(
- ctx->pipe->screen, layer->sampler_view->texture,
- 0, 0, 0,
- PIPE_BIND_RENDER_TARGET);
-
- surface_fill(surface,
- layer->width, layer->height,
- x, y, width, height, alpha_color);
-
- ctx->pipe->screen->tex_surface_release(ctx->pipe->screen, &surface);
+ mask_resource_fill(layer->sampler_view->texture,
+ x, y, width, height, value);
}
void mask_copy(struct vg_mask_layer *layer,
@@ -551,16 +399,27 @@ void mask_copy(struct vg_mask_layer *layer,
VGint dx, VGint dy,
VGint width, VGint height)
{
- struct vg_context *ctx = vg_current_context();
- struct st_framebuffer *fb_buffers = ctx->draw_buffer;
-
- renderer_copy_texture(ctx->renderer,
- layer->sampler_view,
- sx, sy,
- sx + width, sy + height,
- fb_buffers->alpha_mask_view->texture,
- dx, dy,
- dx + width, dy + height);
+ struct vg_context *ctx = vg_current_context();
+ struct pipe_sampler_view *src = vg_get_surface_mask(ctx);
+ struct pipe_surface *surf, surf_tmpl;
+
+ /* get the destination surface */
+ u_surface_default_template(&surf_tmpl, layer->sampler_view->texture,
+ PIPE_BIND_RENDER_TARGET);
+ surf = ctx->pipe->create_surface(ctx->pipe, layer->sampler_view->texture,
+ &surf_tmpl);
+ if (surf && renderer_copy_begin(ctx->renderer, surf, VG_FALSE, src)) {
+ /* layer should be flipped when used as a texture */
+ sy += height;
+ height = -height;
+
+ renderer_copy(ctx->renderer,
+ dx, dy, width, height,
+ sx, sy, width, height);
+ renderer_copy_end(ctx->renderer);
+ }
+
+ pipe_surface_reference(&surf, NULL);
}
static void mask_layer_render_to(struct vg_mask_layer *layer,
@@ -568,41 +427,25 @@ static void mask_layer_render_to(struct vg_mask_layer *layer,
VGbitfield paint_modes)
{
struct vg_context *ctx = vg_current_context();
- const VGfloat fill_color[4] = {1.f, 1.f, 1.f, 1.f};
- struct pipe_screen *screen = ctx->pipe->screen;
- struct pipe_surface *surface;
-
- surface = screen->get_tex_surface(screen, layer->sampler_view->texture, 0, 0, 0,
- PIPE_BIND_RENDER_TARGET);
-
- cso_save_framebuffer(ctx->cso_context);
- cso_save_fragment_shader(ctx->cso_context);
- cso_save_viewport(ctx->cso_context);
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_sampler_view *view = vg_get_surface_mask(ctx);
+ struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
+ struct pipe_surface *surf, surf_tmpl;
+ u_surface_default_template(&surf_tmpl, view->texture,
+ PIPE_BIND_RENDER_TARGET);
+ surf = pipe->create_surface(pipe, view->texture, &surf_tmpl);
- setup_mask_blend();
- setup_mask_fill(fill_color);
- setup_mask_framebuffer(surface, layer->width, layer->height);
- setup_mask_viewport();
+ renderer_validate_for_mask_rendering(ctx->renderer, surf, mat);
if (paint_modes & VG_FILL_PATH) {
- struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
- path_fill(path, mat);
+ path_fill(path);
}
if (paint_modes & VG_STROKE_PATH){
path_stroke(path);
}
-
- /* make sure rendering has completed */
- ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
-
- cso_restore_framebuffer(ctx->cso_context);
- cso_restore_fragment_shader(ctx->cso_context);
- cso_restore_viewport(ctx->cso_context);
- ctx->state.dirty |= BLEND_DIRTY;
-
- screen->tex_surface_release(ctx->pipe->screen, &surface);
+ pipe_surface_reference(&surf, NULL);
}
void mask_render_to(struct path *path,
@@ -610,19 +453,19 @@ void mask_render_to(struct path *path,
VGMaskOperation operation)
{
struct vg_context *ctx = vg_current_context();
- struct st_framebuffer *fb_buffers = ctx->draw_buffer;
+ struct st_framebuffer *stfb = ctx->draw_buffer;
struct vg_mask_layer *temp_layer;
VGint width, height;
- width = fb_buffers->alpha_mask_view->texture->width0;
- height = fb_buffers->alpha_mask_view->texture->width0;
+ width = stfb->width;
+ height = stfb->height;
temp_layer = mask_layer_create(width, height);
+ mask_layer_fill(temp_layer, 0, 0, width, height, 0.0f);
mask_layer_render_to(temp_layer, path, paint_modes);
- mask_using_layer(temp_layer, 0, 0, width, height,
- operation);
+ mask_using_layer(temp_layer, operation, 0, 0, width, height);
mask_layer_destroy(temp_layer);
}
@@ -632,7 +475,7 @@ void mask_using_layer(struct vg_mask_layer *layer,
VGint x, VGint y,
VGint width, VGint height)
{
- mask_using_texture(layer->sampler_view, operation,
+ mask_using_texture(layer->sampler_view, VG_TRUE, operation,
x, y, width, height);
}
@@ -654,7 +497,7 @@ void mask_using_image(struct vg_image *image,
VGint x, VGint y,
VGint width, VGint height)
{
- mask_using_texture(image->sampler_view, operation,
+ mask_using_texture(image->sampler_view, VG_FALSE, operation,
x, y, width, height);
}
@@ -662,23 +505,15 @@ void mask_fill(VGint x, VGint y, VGint width, VGint height,
VGfloat value)
{
struct vg_context *ctx = vg_current_context();
- VGfloat alpha_color[4] = {.0f, .0f, .0f, value};
- struct pipe_surface *surf = alpha_mask_surface(
- ctx, PIPE_BIND_RENDER_TARGET);
+ struct pipe_sampler_view *view = vg_get_surface_mask(ctx);
#if DEBUG_MASKS
debug_printf("mask_fill(%d, %d, %d, %d) with rgba(%f, %f, %f, %f)\n",
x, y, width, height,
- alpha_color[0], alpha_color[1],
- alpha_color[2], alpha_color[3]);
- debug_printf("XXX %f === %f \n",
- alpha_color[3], value);
+ 0.0f, 0.0f, 0.0f, value);
#endif
- surface_fill(surf, surf->width, surf->height,
- x, y, width, height, alpha_color);
-
- pipe_surface_reference(&surf, NULL);
+ mask_resource_fill(view->texture, x, y, width, height, value);
}
VGint mask_bind_samplers(struct pipe_sampler_state **samplers,
@@ -687,10 +522,8 @@ VGint mask_bind_samplers(struct pipe_sampler_state **samplers,
struct vg_context *ctx = vg_current_context();
if (ctx->state.vg.masking) {
- struct st_framebuffer *fb_buffers = ctx->draw_buffer;
-
samplers[1] = &ctx->mask.sampler;
- sampler_views[1] = fb_buffers->alpha_mask_view;
+ sampler_views[1] = vg_get_surface_mask(ctx);
return 1;
} else
return 0;
diff --git a/src/gallium/state_trackers/vega/matrix.h b/src/gallium/state_trackers/vega/matrix.h
index 4c207f912a8..bed2b3193d0 100644
--- a/src/gallium/state_trackers/vega/matrix.h
+++ b/src/gallium/state_trackers/vega/matrix.h
@@ -129,7 +129,7 @@ static INLINE void matrix_make_affine(struct matrix *matrix)
}
static INLINE void matrix_mult(struct matrix *dst,
- struct matrix *src)
+ const struct matrix *src)
{
VGfloat m11 = dst->m[0]*src->m[0] + dst->m[3]*src->m[1] + dst->m[6]*src->m[2];
VGfloat m12 = dst->m[0]*src->m[3] + dst->m[3]*src->m[4] + dst->m[6]*src->m[5];
diff --git a/src/gallium/state_trackers/vega/paint.c b/src/gallium/state_trackers/vega/paint.c
index c0c8cddabe9..2db8cbcf7c8 100644
--- a/src/gallium/state_trackers/vega/paint.c
+++ b/src/gallium/state_trackers/vega/paint.c
@@ -28,7 +28,6 @@
#include "matrix.h"
#include "image.h"
-#include "st_inlines.h"
#include "pipe/p_compiler.h"
#include "util/u_inlines.h"
@@ -155,14 +154,15 @@ static INLINE struct pipe_resource *create_gradient_texture(struct vg_paint *p)
templ.width0 = 1024;
templ.height0 = 1;
templ.depth0 = 1;
+ templ.array_size = 1;
templ.bind = PIPE_BIND_SAMPLER_VIEW;
tex = screen->resource_create(screen, &templ);
{ /* upload color_data */
struct pipe_transfer *transfer =
- st_no_flush_get_transfer(p->base.ctx, tex, 0, 0, 0,
- PIPE_TRANSFER_WRITE, 0, 0, 1024, 1);
+ pipe_get_transfer(p->base.ctx->pipe, tex, 0, 0,
+ PIPE_TRANSFER_WRITE, 0, 0, 1024, 1);
void *map = pipe->transfer_map(pipe, transfer);
memcpy(map, p->gradient.color_data, sizeof(VGint)*1024);
pipe->transfer_unmap(pipe, transfer);
@@ -261,14 +261,18 @@ static INLINE void paint_color_buffer(struct vg_paint *paint, void *buffer)
map[7] = 4.f;
}
-static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *buffer)
+static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint,
+ const struct matrix *inv,
+ void *buffer)
{
- struct vg_context *ctx = paint->base.ctx;
VGfloat *map = (VGfloat*)buffer;
+ VGfloat dd;
map[0] = paint->gradient.linear.coords[2] - paint->gradient.linear.coords[0];
map[1] = paint->gradient.linear.coords[3] - paint->gradient.linear.coords[1];
- map[2] = 1.f / (map[0] * map[0] + map[1] * map[1]);
+ dd = (map[0] * map[0] + map[1] * map[1]);
+
+ map[2] = (dd > 0.0f) ? 1.f / dd : 0.f;
map[3] = 1.f;
map[4] = 0.f;
@@ -277,15 +281,10 @@ static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *bu
map[7] = 4.f;
{
struct matrix mat;
- struct matrix inv;
matrix_load_identity(&mat);
+ /* VEGA_LINEAR_GRADIENT_SHADER expects the first point to be at (0, 0) */
matrix_translate(&mat, -paint->gradient.linear.coords[0], -paint->gradient.linear.coords[1]);
- memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
- sizeof(struct matrix));
- matrix_invert(&inv);
- matrix_mult(&inv, &mat);
- memcpy(&mat, &inv,
- sizeof(struct matrix));
+ matrix_mult(&mat, inv);
map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
@@ -298,17 +297,37 @@ static INLINE void paint_linear_gradient_buffer(struct vg_paint *paint, void *bu
}
-static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *buffer)
+static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint,
+ const struct matrix *inv,
+ void *buffer)
{
- VGfloat *radialCoords = paint->gradient.radial.vals;
- struct vg_context *ctx = paint->base.ctx;
-
+ const VGfloat *center = &paint->gradient.radial.vals[0];
+ const VGfloat *focal = &paint->gradient.radial.vals[2];
+ VGfloat rr = paint->gradient.radial.vals[4];
VGfloat *map = (VGfloat*)buffer;
+ VGfloat dd, new_focal[2];
+
+ rr *= rr;
+
+ map[0] = center[0] - focal[0];
+ map[1] = center[1] - focal[1];
+ dd = map[0] * map[0] + map[1] * map[1];
+
+ /* focal point must lie inside the circle */
+ if (0.998f * rr < dd) {
+ VGfloat scale;
+
+ scale = (dd > 0.0f) ? sqrt(0.998f * rr / dd) : 0.0f;
+ map[0] *= scale;
+ map[1] *= scale;
- map[0] = radialCoords[0] - radialCoords[2];
- map[1] = radialCoords[1] - radialCoords[3];
- map[2] = -map[0] * map[0] - map[1] * map[1] +
- radialCoords[4] * radialCoords[4];
+ new_focal[0] = center[0] - map[0];
+ new_focal[1] = center[1] - map[1];
+ dd = map[0] * map[0] + map[1] * map[1];
+ focal = new_focal;
+ }
+
+ map[2] = (rr > dd) ? rr - dd : 1.0f;
map[3] = 1.f;
map[4] = 0.f;
@@ -318,15 +337,9 @@ static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *bu
{
struct matrix mat;
- struct matrix inv;
matrix_load_identity(&mat);
- matrix_translate(&mat, -radialCoords[2], -radialCoords[3]);
- memcpy(&inv, &ctx->state.vg.fill_paint_to_user_matrix,
- sizeof(struct matrix));
- matrix_invert(&inv);
- matrix_mult(&inv, &mat);
- memcpy(&mat, &inv,
- sizeof(struct matrix));
+ matrix_translate(&mat, -focal[0], -focal[1]);
+ matrix_mult(&mat, inv);
map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
@@ -340,10 +353,10 @@ static INLINE void paint_radial_gradient_buffer(struct vg_paint *paint, void *bu
}
-static INLINE void paint_pattern_buffer(struct vg_paint *paint, void *buffer)
+static INLINE void paint_pattern_buffer(struct vg_paint *paint,
+ const struct matrix *inv,
+ void *buffer)
{
- struct vg_context *ctx = paint->base.ctx;
-
VGfloat *map = (VGfloat *)buffer;
memcpy(map, paint->solid.color, 4 * sizeof(VGfloat));
@@ -353,17 +366,8 @@ static INLINE void paint_pattern_buffer(struct vg_paint *paint, void *buffer)
map[7] = paint->pattern.sampler_view->texture->height0;
{
struct matrix mat;
- memcpy(&mat, &ctx->state.vg.fill_paint_to_user_matrix,
- sizeof(struct matrix));
- matrix_invert(&mat);
- {
- struct matrix pm;
- memcpy(&pm, &ctx->state.vg.path_user_to_surface_matrix,
- sizeof(struct matrix));
- matrix_invert(&pm);
- matrix_mult(&pm, &mat);
- memcpy(&mat, &pm, sizeof(struct matrix));
- }
+
+ memcpy(&mat, inv, sizeof(*inv));
map[8] = mat.m[0]; map[9] = mat.m[3]; map[10] = mat.m[6]; map[11] = 0.f;
map[12] = mat.m[1]; map[13] = mat.m[4]; map[14] = mat.m[7]; map[15] = 0.f;
@@ -672,6 +676,34 @@ void paint_resolve_type(struct vg_paint *paint)
}
}
+VGboolean paint_is_degenerate(struct vg_paint *paint)
+{
+ VGboolean degen;
+ VGfloat *vals;
+
+
+ switch (paint->type) {
+ case VG_PAINT_TYPE_LINEAR_GRADIENT:
+ vals = paint->gradient.linear.coords;
+ /* two points are coincident */
+ degen = (floatsEqual(vals[0], vals[2]) &&
+ floatsEqual(vals[1], vals[3]));
+ break;
+ case VG_PAINT_TYPE_RADIAL_GRADIENT:
+ vals = paint->gradient.radial.vals;
+ /* radius <= 0 */
+ degen = (vals[4] <= 0.0f);
+ break;
+ case VG_PAINT_TYPE_COLOR:
+ case VG_PAINT_TYPE_PATTERN:
+ default:
+ degen = VG_FALSE;
+ break;
+ }
+
+ return degen;
+}
+
VGint paint_constant_buffer_size(struct vg_paint *paint)
{
switch(paint->type) {
@@ -695,6 +727,7 @@ VGint paint_constant_buffer_size(struct vg_paint *paint)
}
void paint_fill_constant_buffer(struct vg_paint *paint,
+ const struct matrix *mat,
void *buffer)
{
switch(paint->type) {
@@ -702,13 +735,13 @@ void paint_fill_constant_buffer(struct vg_paint *paint,
paint_color_buffer(paint, buffer);
break;
case VG_PAINT_TYPE_LINEAR_GRADIENT:
- paint_linear_gradient_buffer(paint, buffer);
+ paint_linear_gradient_buffer(paint, mat, buffer);
break;
case VG_PAINT_TYPE_RADIAL_GRADIENT:
- paint_radial_gradient_buffer(paint, buffer);
+ paint_radial_gradient_buffer(paint, mat, buffer);
break;
case VG_PAINT_TYPE_PATTERN:
- paint_pattern_buffer(paint, buffer);
+ paint_pattern_buffer(paint, mat, buffer);
break;
default:
diff --git a/src/gallium/state_trackers/vega/paint.h b/src/gallium/state_trackers/vega/paint.h
index 012cd3e5618..3de3bbe12ed 100644
--- a/src/gallium/state_trackers/vega/paint.h
+++ b/src/gallium/state_trackers/vega/paint.h
@@ -110,8 +110,12 @@ VGboolean paint_color_ramp_premultiplied(struct vg_paint *paint);
VGint paint_bind_samplers(struct vg_paint *paint, struct pipe_sampler_state **samplers,
struct pipe_sampler_view **sampler_views);
+VGboolean paint_is_degenerate(struct vg_paint *paint);
+
VGint paint_constant_buffer_size(struct vg_paint *paint);
+
void paint_fill_constant_buffer(struct vg_paint *paint,
+ const struct matrix *mat,
void *buffer);
diff --git a/src/gallium/state_trackers/vega/path.c b/src/gallium/state_trackers/vega/path.c
index 05f8b0d9979..d7253befd03 100644
--- a/src/gallium/state_trackers/vega/path.c
+++ b/src/gallium/state_trackers/vega/path.c
@@ -207,13 +207,29 @@ struct path * path_create(VGPathDatatype dt, VGfloat scale, VGfloat bias,
return path;
}
+static void polygon_array_cleanup(struct polygon_array *polyarray)
+{
+ if (polyarray->array) {
+ VGint i;
+
+ for (i = 0; i < polyarray->array->num_elements; i++) {
+ struct polygon *p = ((struct polygon **) polyarray->array->data)[i];
+ polygon_destroy(p);
+ }
+
+ array_destroy(polyarray->array);
+ polyarray->array = NULL;
+ }
+}
+
void path_destroy(struct path *p)
{
vg_context_remove_object(vg_current_context(), VG_OBJECT_PATH, p);
array_destroy(p->segments);
array_destroy(p->control_points);
- array_destroy(p->fill_polys.polygon_array.array);
+
+ polygon_array_cleanup(&p->fill_polys.polygon_array);
if (p->stroked.path)
path_destroy(p->stroked.path);
@@ -302,7 +318,6 @@ static void convert_path(struct path *p,
}
}
-
static void polygon_array_calculate_bounds( struct polygon_array *polyarray )
{
struct array *polys = polyarray->array;
@@ -312,7 +327,15 @@ static void polygon_array_calculate_bounds( struct polygon_array *polyarray )
unsigned i;
assert(polys);
- assert(polys->num_elements);
+
+ if (!polys->num_elements) {
+ polyarray->min_x = 0.0f;
+ polyarray->min_y = 0.0f;
+ polyarray->max_x = 0.0f;
+ polyarray->max_y = 0.0f;
+ return;
+ }
+
polygon_bounding_rect((((struct polygon**)polys->data)[0]), bounds);
min_x = bounds[0];
min_y = bounds[1];
@@ -353,16 +376,17 @@ static struct polygon_array * path_get_fill_polygons(struct path *p, struct matr
return &p->fill_polys.polygon_array;
}
else {
- array_destroy( p->fill_polys.polygon_array.array );
- p->fill_polys.polygon_array.array = NULL;
+ polygon_array_cleanup(&p->fill_polys.polygon_array);
}
}
- array = array_create(sizeof(struct array*));
+ /* an array of pointers to polygons */
+ array = array_create(sizeof(struct polygon *));
sx = sy = px = py = ox = oy = 0.f;
- current = polygon_create(32);
+ if (p->num_segments)
+ current = polygon_create(32);
for (i = 0; i < p->num_segments; ++i) {
VGubyte segment = ((VGubyte*)(p->segments->data))[i];
@@ -1519,10 +1543,11 @@ struct path * path_create_stroke(struct path *p,
return stroker.base.path;
}
-void path_render(struct path *p, VGbitfield paintModes)
+void path_render(struct path *p, VGbitfield paintModes,
+ struct matrix *mat)
{
struct vg_context *ctx = vg_current_context();
- struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
+ struct matrix paint_matrix;
vg_validate_state(ctx);
@@ -1534,29 +1559,45 @@ void path_render(struct path *p, VGbitfield paintModes)
mat->m[3], mat->m[4], mat->m[5],
mat->m[6], mat->m[7], mat->m[8]);
#endif
- if (paintModes & VG_FILL_PATH) {
+ if ((paintModes & VG_FILL_PATH) &&
+ vg_get_paint_matrix(ctx,
+ &ctx->state.vg.fill_paint_to_user_matrix,
+ mat,
+ &paint_matrix)) {
/* First the fill */
+ shader_set_surface_matrix(ctx->shader, mat);
shader_set_paint(ctx->shader, ctx->state.vg.fill_paint);
+ shader_set_paint_matrix(ctx->shader, &paint_matrix);
shader_bind(ctx->shader);
- path_fill(p, mat);
+ path_fill(p);
}
- if (paintModes & VG_STROKE_PATH){
+ if ((paintModes & VG_STROKE_PATH) &&
+ vg_get_paint_matrix(ctx,
+ &ctx->state.vg.stroke_paint_to_user_matrix,
+ mat,
+ &paint_matrix)) {
/* 8.7.5: "line width less than or equal to 0 prevents stroking from
* taking place."*/
if (ctx->state.vg.stroke.line_width.f <= 0)
return;
+ shader_set_surface_matrix(ctx->shader, mat);
shader_set_paint(ctx->shader, ctx->state.vg.stroke_paint);
+ shader_set_paint_matrix(ctx->shader, &paint_matrix);
shader_bind(ctx->shader);
path_stroke(p);
}
}
-void path_fill(struct path *p, struct matrix *mat)
+void path_fill(struct path *p)
{
struct vg_context *ctx = vg_current_context();
+ struct matrix identity;
+
+ matrix_load_identity(&identity);
+
{
- struct polygon_array *polygon_array = path_get_fill_polygons(p, mat);
+ struct polygon_array *polygon_array = path_get_fill_polygons(p, &identity);
struct array *polys = polygon_array->array;
if (!polygon_array || !polys || !polys->num_elements) {
@@ -1569,7 +1610,6 @@ void path_fill(struct path *p, struct matrix *mat)
void path_stroke(struct path *p)
{
struct vg_context *ctx = vg_current_context();
- struct matrix *mat = &ctx->state.vg.path_user_to_surface_matrix;
VGFillRule old_fill = ctx->state.vg.fill_rule;
struct matrix identity;
struct path *stroke;
@@ -1579,7 +1619,7 @@ void path_stroke(struct path *p)
if (stroke && !path_is_empty(stroke)) {
ctx->state.vg.fill_rule = VG_NON_ZERO;
- path_fill(stroke, mat);
+ path_fill(stroke);
ctx->state.vg.fill_rule = old_fill;
}
diff --git a/src/gallium/state_trackers/vega/path.h b/src/gallium/state_trackers/vega/path.h
index e34538b7368..d84b1f083ce 100644
--- a/src/gallium/state_trackers/vega/path.h
+++ b/src/gallium/state_trackers/vega/path.h
@@ -104,8 +104,8 @@ VGboolean path_interpolate(struct path *dst,
VGfloat amount);
void path_clear(struct path *p, VGbitfield capabilities);
-void path_render(struct path *p, VGbitfield paintModes);
-void path_fill(struct path *p, struct matrix *mat);
+void path_render(struct path *p, VGbitfield paintModes, struct matrix *mat);
+void path_fill(struct path *p);
void path_stroke(struct path *p);
void path_move_to(struct path *p, float x, float y);
diff --git a/src/gallium/state_trackers/vega/polygon.c b/src/gallium/state_trackers/vega/polygon.c
index ca8831064c9..a491de27fa6 100644
--- a/src/gallium/state_trackers/vega/polygon.c
+++ b/src/gallium/state_trackers/vega/polygon.c
@@ -244,24 +244,11 @@ VGboolean polygon_is_closed(struct polygon *p)
return floatsEqual(start[0], end[0]) && floatsEqual(start[1], end[1]);
}
-static void set_blend_for_fill(struct pipe_blend_state *blend)
-{
- memset(blend, 0, sizeof(struct pipe_blend_state));
- blend->rt[0].colormask = 0; /*disable colorwrites*/
-
- blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
- blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
-}
-
-static void draw_polygon(struct vg_context *ctx,
- struct polygon *poly)
+static void polygon_prepare_buffer(struct vg_context *ctx,
+ struct polygon *poly)
{
int vert_size;
struct pipe_context *pipe;
- struct pipe_vertex_buffer vbuffer;
- struct pipe_vertex_element velement;
vert_size = poly->num_verts * COMPONENTS * sizeof(float);
@@ -281,35 +268,15 @@ static void draw_polygon(struct vg_context *ctx,
PIPE_BIND_VERTEX_BUFFER);
poly->dirty = VG_FALSE;
}
-
-
- /* tell pipe about the vertex buffer */
- memset(&vbuffer, 0, sizeof(vbuffer));
- vbuffer.buffer = poly->vbuf;
- vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
- vbuffer.buffer_offset = 0;
- vbuffer.max_index = poly->num_verts - 1;
- pipe->set_vertex_buffers(pipe, 1, &vbuffer);
-
- /* tell pipe about the vertex attributes */
- memset(&velement, 0, sizeof(velement));
- velement.src_offset = 0;
- velement.instance_divisor = 0;
- velement.vertex_buffer_index = 0;
- velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
- cso_set_vertex_elements(ctx->cso_context, 1, &velement);
-
- /* draw */
- util_draw_arrays(pipe, PIPE_PRIM_TRIANGLE_FAN, 0, (uint) poly->num_verts);
}
void polygon_fill(struct polygon *poly, struct vg_context *ctx)
{
- struct pipe_depth_stencil_alpha_state dsa;
- struct pipe_stencil_ref sr;
- struct pipe_blend_state blend;
+ struct pipe_vertex_element velement;
+ struct pipe_vertex_buffer vbuffer;
VGfloat bounds[4];
VGfloat min_x, min_y, max_x, max_y;
+
assert(poly);
polygon_bounding_rect(poly, bounds);
min_x = bounds[0];
@@ -322,113 +289,42 @@ void polygon_fill(struct polygon *poly, struct vg_context *ctx)
min_x, min_y, max_x, max_y);
#endif
- set_blend_for_fill(&blend);
-
- memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
- memset(&sr, 0, sizeof(struct pipe_stencil_ref));
- /* only need a fixed 0. Rely on default or move it out at least? */
- cso_set_stencil_ref(ctx->cso_context, &sr);
-
- cso_save_blend(ctx->cso_context);
- cso_save_depth_stencil_alpha(ctx->cso_context);
-
- dsa.stencil[0].enabled = 1;
- if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
- dsa.stencil[0].writemask = 1;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
- dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
- dsa.stencil[0].valuemask = ~0;
-
- cso_set_blend(ctx->cso_context, &blend);
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
- draw_polygon(ctx, poly);
- } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
- struct pipe_screen *screen = ctx->pipe->screen;
-
- if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
- /* front */
- dsa.stencil[0].writemask = ~0;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
- dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
- dsa.stencil[0].valuemask = ~0;
-
- /* back */
- dsa.stencil[1].enabled = 1;
- dsa.stencil[1].writemask = ~0;
- dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
- dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
- dsa.stencil[1].valuemask = ~0;
-
- cso_set_blend(ctx->cso_context, &blend);
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
- draw_polygon(ctx, poly);
- } else {
- struct pipe_rasterizer_state raster;
-
- memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
-
- cso_save_rasterizer(ctx->cso_context);
- dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
- dsa.stencil[0].valuemask = ~0;
-
- raster.cull_face = PIPE_FACE_BACK;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
-
- cso_set_blend(ctx->cso_context, &blend);
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
- cso_set_rasterizer(ctx->cso_context, &raster);
- draw_polygon(ctx, poly);
-
- raster.cull_face = PIPE_FACE_FRONT;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
- cso_set_rasterizer(ctx->cso_context, &raster);
- draw_polygon(ctx, poly);
-
- cso_restore_rasterizer(ctx->cso_context);
- }
- }
+ polygon_prepare_buffer(ctx, poly);
+
+ /* tell renderer about the vertex attributes */
+ memset(&velement, 0, sizeof(velement));
+ velement.src_offset = 0;
+ velement.instance_divisor = 0;
+ velement.vertex_buffer_index = 0;
+ velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* tell renderer about the vertex buffer */
+ memset(&vbuffer, 0, sizeof(vbuffer));
+ vbuffer.buffer = poly->vbuf;
+ vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
+ vbuffer.buffer_offset = 0;
+ vbuffer.max_index = poly->num_verts - 1;
+
+ renderer_polygon_stencil_begin(ctx->renderer,
+ &velement, ctx->state.vg.fill_rule, VG_FALSE);
+ renderer_polygon_stencil(ctx->renderer, &vbuffer,
+ PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
+ renderer_polygon_stencil_end(ctx->renderer);
- /* restore color writes */
- cso_restore_blend(ctx->cso_context);
- /* setup stencil ops */
- dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
- dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
- dsa.stencil[1].enabled = 0;
- memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
- sizeof(struct pipe_depth_state));
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
-
- /* render the quad to propagate the rendering from stencil */
- renderer_draw_quad(ctx->renderer, min_x, min_y,
- max_x, max_y, 0.0f/*depth should be disabled*/);
-
- cso_restore_depth_stencil_alpha(ctx->cso_context);
+ renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
+ renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
+ renderer_polygon_fill_end(ctx->renderer);
}
void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
{
struct array *polys = polyarray->array;
- struct pipe_depth_stencil_alpha_state dsa;
- struct pipe_stencil_ref sr;
- struct pipe_blend_state blend;
VGfloat min_x = polyarray->min_x;
VGfloat min_y = polyarray->min_y;
VGfloat max_x = polyarray->max_x;
VGfloat max_y = polyarray->max_y;
+ struct pipe_vertex_element velement;
+ struct pipe_vertex_buffer vbuffer;
VGint i;
@@ -438,111 +334,35 @@ void polygon_array_fill(struct polygon_array *polyarray, struct vg_context *ctx)
min_x, min_y, max_x, max_y);
#endif
- set_blend_for_fill(&blend);
-
- memset(&dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
- memset(&sr, 0, sizeof(struct pipe_stencil_ref));
- /* only need a fixed 0. Rely on default or move it out at least? */
- cso_set_stencil_ref(ctx->cso_context, &sr);
-
- cso_save_blend(ctx->cso_context);
- cso_save_depth_stencil_alpha(ctx->cso_context);
-
- dsa.stencil[0].enabled = 1;
- if (ctx->state.vg.fill_rule == VG_EVEN_ODD) {
- dsa.stencil[0].writemask = 1;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
- dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
- dsa.stencil[0].valuemask = ~0;
-
- cso_set_blend(ctx->cso_context, &blend);
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
- for (i = 0; i < polys->num_elements; ++i) {
- struct polygon *poly = (((struct polygon**)polys->data)[i]);
- draw_polygon(ctx, poly);
- }
- } else if (ctx->state.vg.fill_rule == VG_NON_ZERO) {
- struct pipe_screen *screen = ctx->pipe->screen;
-
- if (screen->get_param(screen, PIPE_CAP_TWO_SIDED_STENCIL)) {
- /* front */
- dsa.stencil[0].writemask = ~0;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
- dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
- dsa.stencil[0].valuemask = ~0;
-
- /* back */
- dsa.stencil[1].enabled = 1;
- dsa.stencil[1].writemask = ~0;
- dsa.stencil[1].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[1].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
- dsa.stencil[1].func = PIPE_FUNC_ALWAYS;
- dsa.stencil[1].valuemask = ~0;
-
- cso_set_blend(ctx->cso_context, &blend);
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
- for (i = 0; i < polys->num_elements; ++i) {
- struct polygon *poly = (((struct polygon**)polys->data)[i]);
- draw_polygon(ctx, poly);
- }
- } else {
- struct pipe_rasterizer_state raster;
-
- memcpy(&raster, &ctx->state.g3d.rasterizer, sizeof(struct pipe_rasterizer_state));
-
- cso_save_rasterizer(ctx->cso_context);
- dsa.stencil[0].func = PIPE_FUNC_ALWAYS;
- dsa.stencil[0].valuemask = ~0;
-
- raster.cull_face = PIPE_FACE_BACK;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
-
- cso_set_blend(ctx->cso_context, &blend);
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
- cso_set_rasterizer(ctx->cso_context, &raster);
- for (i = 0; i < polys->num_elements; ++i) {
- struct polygon *poly = (((struct polygon**)polys->data)[i]);
- draw_polygon(ctx, poly);
- }
-
- raster.cull_face = PIPE_FACE_FRONT;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
- cso_set_rasterizer(ctx->cso_context, &raster);
- for (i = 0; i < polys->num_elements; ++i) {
- struct polygon *poly = (((struct polygon**)polys->data)[i]);
- draw_polygon(ctx, poly);
- }
-
- cso_restore_rasterizer(ctx->cso_context);
- }
+ /* tell renderer about the vertex attributes */
+ memset(&velement, 0, sizeof(velement));
+ velement.src_offset = 0;
+ velement.instance_divisor = 0;
+ velement.vertex_buffer_index = 0;
+ velement.src_format = PIPE_FORMAT_R32G32_FLOAT;
+
+ /* tell renderer about the vertex buffer */
+ memset(&vbuffer, 0, sizeof(vbuffer));
+ vbuffer.stride = COMPONENTS * sizeof(float); /* vertex size */
+ vbuffer.buffer_offset = 0;
+
+ /* prepare the stencil buffer */
+ renderer_polygon_stencil_begin(ctx->renderer,
+ &velement, ctx->state.vg.fill_rule, VG_FALSE);
+ for (i = 0; i < polys->num_elements; ++i) {
+ struct polygon *poly = (((struct polygon**)polys->data)[i]);
+
+ polygon_prepare_buffer(ctx, poly);
+ vbuffer.buffer = poly->vbuf;
+ vbuffer.max_index = poly->num_verts - 1;
+
+ renderer_polygon_stencil(ctx->renderer, &vbuffer,
+ PIPE_PRIM_TRIANGLE_FAN, 0, (VGuint) poly->num_verts);
}
+ renderer_polygon_stencil_end(ctx->renderer);
- /* restore color writes */
- cso_restore_blend(ctx->cso_context);
- /* setup stencil ops */
- dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
- dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
- dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
- dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
- dsa.stencil[0].valuemask = dsa.stencil[0].writemask;
- dsa.stencil[1].enabled = 0;
- memcpy(&dsa.depth, &ctx->state.g3d.dsa.depth,
- sizeof(struct pipe_depth_state));
- cso_set_depth_stencil_alpha(ctx->cso_context, &dsa);
-
- /* render the quad to propagate the rendering from stencil */
- renderer_draw_quad(ctx->renderer, min_x, min_y,
- max_x, max_y, 0.0f/*depth should be disabled*/);
-
- cso_restore_depth_stencil_alpha(ctx->cso_context);
+ /* fill it */
+ renderer_polygon_fill_begin(ctx->renderer, VG_FALSE);
+ renderer_polygon_fill(ctx->renderer, min_x, min_y, max_x, max_y);
+ renderer_polygon_fill_end(ctx->renderer);
}
diff --git a/src/gallium/state_trackers/vega/renderer.c b/src/gallium/state_trackers/vega/renderer.c
index c6f5f7a05b8..7871c516c41 100644
--- a/src/gallium/state_trackers/vega/renderer.c
+++ b/src/gallium/state_trackers/vega/renderer.c
@@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
+ * Copyright 2010 LunarG, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -27,6 +28,7 @@
#include "renderer.h"
#include "vg_context.h"
+#include "image.h"
#include "pipe/p_context.h"
#include "pipe/p_state.h"
@@ -38,364 +40,1382 @@
#include "util/u_simple_shaders.h"
#include "util/u_memory.h"
#include "util/u_sampler.h"
+#include "util/u_surface.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
#include "cso_cache/cso_context.h"
+#include "tgsi/tgsi_ureg.h"
+
+typedef enum {
+ RENDERER_STATE_INIT,
+ RENDERER_STATE_COPY,
+ RENDERER_STATE_DRAWTEX,
+ RENDERER_STATE_SCISSOR,
+ RENDERER_STATE_CLEAR,
+ RENDERER_STATE_FILTER,
+ RENDERER_STATE_POLYGON_STENCIL,
+ RENDERER_STATE_POLYGON_FILL,
+ NUM_RENDERER_STATES
+} RendererState;
+
+typedef enum {
+ RENDERER_VS_PLAIN,
+ RENDERER_VS_COLOR,
+ RENDERER_VS_TEXTURE,
+ NUM_RENDERER_VS
+} RendererVs;
+
+typedef enum {
+ RENDERER_FS_COLOR,
+ RENDERER_FS_TEXTURE,
+ RENDERER_FS_SCISSOR,
+ RENDERER_FS_WHITE,
+ NUM_RENDERER_FS
+} RendererFs;
struct renderer {
struct pipe_context *pipe;
- struct vg_context *owner;
-
struct cso_context *cso;
- void *fs;
+ VGbitfield dirty;
+ struct {
+ struct pipe_rasterizer_state rasterizer;
+ struct pipe_depth_stencil_alpha_state dsa;
+ struct pipe_framebuffer_state fb;
+ } g3d;
+ struct matrix projection;
+
+ struct matrix mvp;
+ struct pipe_resource *vs_cbuf;
+
+ struct pipe_resource *fs_cbuf;
+ VGfloat fs_cbuf_data[32];
+ VGint fs_cbuf_len;
+ struct pipe_vertex_element velems[2];
VGfloat vertices[4][2][4];
+
+ void *cached_vs[NUM_RENDERER_VS];
+ void *cached_fs[NUM_RENDERER_FS];
+
+ RendererState state;
+
+ /* state data */
+ union {
+ struct {
+ VGint tex_width;
+ VGint tex_height;
+ } copy;
+
+ struct {
+ VGint tex_width;
+ VGint tex_height;
+ } drawtex;
+
+ struct {
+ VGboolean restore_dsa;
+ } scissor;
+
+ struct {
+ VGboolean use_sampler;
+ VGint tex_width, tex_height;
+ } filter;
+
+ struct {
+ struct pipe_depth_stencil_alpha_state dsa;
+ VGboolean manual_two_sides;
+ VGboolean restore_dsa;
+ } polygon_stencil;
+ } u;
};
-static void setup_shaders(struct renderer *ctx)
+/**
+ * Return VG_TRUE if the renderer can use the resource as the asked bindings.
+ */
+static VGboolean renderer_can_support(struct renderer *renderer,
+ struct pipe_resource *res,
+ unsigned bindings)
{
- struct pipe_context *pipe = ctx->pipe;
- /* fragment shader */
- ctx->fs = util_make_fragment_tex_shader(pipe, TGSI_TEXTURE_2D,
- TGSI_INTERPOLATE_LINEAR);
-}
-
-static struct pipe_resource *
-setup_vertex_data(struct renderer *ctx,
- float x0, float y0, float x1, float y1, float z)
-{
- ctx->vertices[0][0][0] = x0;
- ctx->vertices[0][0][1] = y0;
- ctx->vertices[0][0][2] = z;
- ctx->vertices[0][1][0] = 0.0f; /*s*/
- ctx->vertices[0][1][1] = 0.0f; /*t*/
-
- ctx->vertices[1][0][0] = x1;
- ctx->vertices[1][0][1] = y0;
- ctx->vertices[1][0][2] = z;
- ctx->vertices[1][1][0] = 1.0f; /*s*/
- ctx->vertices[1][1][1] = 0.0f; /*t*/
-
- ctx->vertices[2][0][0] = x1;
- ctx->vertices[2][0][1] = y1;
- ctx->vertices[2][0][2] = z;
- ctx->vertices[2][1][0] = 1.0f;
- ctx->vertices[2][1][1] = 1.0f;
-
- ctx->vertices[3][0][0] = x0;
- ctx->vertices[3][0][1] = y1;
- ctx->vertices[3][0][2] = z;
- ctx->vertices[3][1][0] = 0.0f;
- ctx->vertices[3][1][1] = 1.0f;
-
- return pipe_user_buffer_create( ctx->pipe->screen,
- ctx->vertices,
- sizeof(ctx->vertices),
- PIPE_BIND_VERTEX_BUFFER);
-}
-
-static struct pipe_resource *
-setup_vertex_data_tex(struct renderer *ctx,
- float x0, float y0, float x1, float y1,
- float s0, float t0, float s1, float t1,
- float z)
-{
- ctx->vertices[0][0][0] = x0;
- ctx->vertices[0][0][1] = y0;
- ctx->vertices[0][0][2] = z;
- ctx->vertices[0][1][0] = s0; /*s*/
- ctx->vertices[0][1][1] = t0; /*t*/
-
- ctx->vertices[1][0][0] = x1;
- ctx->vertices[1][0][1] = y0;
- ctx->vertices[1][0][2] = z;
- ctx->vertices[1][1][0] = s1; /*s*/
- ctx->vertices[1][1][1] = t0; /*t*/
-
- ctx->vertices[2][0][0] = x1;
- ctx->vertices[2][0][1] = y1;
- ctx->vertices[2][0][2] = z;
- ctx->vertices[2][1][0] = s1;
- ctx->vertices[2][1][1] = t1;
-
- ctx->vertices[3][0][0] = x0;
- ctx->vertices[3][0][1] = y1;
- ctx->vertices[3][0][2] = z;
- ctx->vertices[3][1][0] = s0;
- ctx->vertices[3][1][1] = t1;
-
- return pipe_user_buffer_create( ctx->pipe->screen,
- ctx->vertices,
- sizeof(ctx->vertices),
- PIPE_BIND_VERTEX_BUFFER);
-}
-
-
-static struct pipe_resource *
-setup_vertex_data_qtex(struct renderer *ctx,
- float x0, float y0, float x1, float y1,
- float x2, float y2, float x3, float y3,
- float s0, float t0, float s1, float t1,
- float z)
-{
- ctx->vertices[0][0][0] = x0;
- ctx->vertices[0][0][1] = y0;
- ctx->vertices[0][0][2] = z;
- ctx->vertices[0][1][0] = s0; /*s*/
- ctx->vertices[0][1][1] = t0; /*t*/
-
- ctx->vertices[1][0][0] = x1;
- ctx->vertices[1][0][1] = y1;
- ctx->vertices[1][0][2] = z;
- ctx->vertices[1][1][0] = s1; /*s*/
- ctx->vertices[1][1][1] = t0; /*t*/
-
- ctx->vertices[2][0][0] = x2;
- ctx->vertices[2][0][1] = y2;
- ctx->vertices[2][0][2] = z;
- ctx->vertices[2][1][0] = s1;
- ctx->vertices[2][1][1] = t1;
-
- ctx->vertices[3][0][0] = x3;
- ctx->vertices[3][0][1] = y3;
- ctx->vertices[3][0][2] = z;
- ctx->vertices[3][1][0] = s0;
- ctx->vertices[3][1][1] = t1;
-
- return pipe_user_buffer_create( ctx->pipe->screen,
- ctx->vertices,
- sizeof(ctx->vertices),
- PIPE_BIND_VERTEX_BUFFER);
+ struct pipe_screen *screen = renderer->pipe->screen;
+
+ return screen->is_format_supported(screen,
+ res->format, res->target, 0, bindings, 0);
}
-struct renderer * renderer_create(struct vg_context *owner)
+/**
+ * Set the model-view-projection matrix used by vertex shaders.
+ */
+static void renderer_set_mvp(struct renderer *renderer,
+ const struct matrix *mvp)
{
+ struct matrix *cur = &renderer->mvp;
+ struct pipe_resource *cbuf;
+ VGfloat consts[3][4];
VGint i;
- struct renderer *renderer = CALLOC_STRUCT(renderer);
- if (!renderer)
+ /* projection only */
+ if (!mvp)
+ mvp = &renderer->projection;
+
+ /* re-upload only if necessary */
+ if (memcmp(cur, mvp, sizeof(*mvp)) == 0)
+ return;
+
+ /* 3x3 matrix to 3 constant vectors (no Z) */
+ for (i = 0; i < 3; i++) {
+ consts[i][0] = mvp->m[i + 0];
+ consts[i][1] = mvp->m[i + 3];
+ consts[i][2] = 0.0f;
+ consts[i][3] = mvp->m[i + 6];
+ }
+
+ cbuf = renderer->vs_cbuf;
+ pipe_resource_reference(&cbuf, NULL);
+ cbuf = pipe_buffer_create(renderer->pipe->screen,
+ PIPE_BIND_CONSTANT_BUFFER,
+ sizeof(consts));
+ if (cbuf) {
+ pipe_buffer_write(renderer->pipe, cbuf,
+ 0, sizeof(consts), consts);
+ }
+ renderer->pipe->set_constant_buffer(renderer->pipe,
+ PIPE_SHADER_VERTEX, 0, cbuf);
+
+ memcpy(cur, mvp, sizeof(*mvp));
+ renderer->vs_cbuf = cbuf;
+}
+
+/**
+ * Create a simple vertex shader that passes through position and the given
+ * attribute.
+ */
+static void *create_passthrough_vs(struct pipe_context *pipe, int semantic_name)
+{
+ struct ureg_program *ureg;
+ struct ureg_src src[2], constants[3];
+ struct ureg_dst dst[2], tmp;
+ int i;
+
+ ureg = ureg_create(TGSI_PROCESSOR_VERTEX);
+ if (!ureg)
return NULL;
- renderer->owner = owner;
- renderer->pipe = owner->pipe;
- renderer->cso = owner->cso_context;
+ /* position is in user coordinates */
+ src[0] = ureg_DECL_vs_input(ureg, 0);
+ dst[0] = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+ tmp = ureg_DECL_temporary(ureg);
+ for (i = 0; i < Elements(constants); i++)
+ constants[i] = ureg_DECL_constant(ureg, i);
+
+ /* transform to clipped coordinates */
+ ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_X), src[0], constants[0]);
+ ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Y), src[0], constants[1]);
+ ureg_MOV(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_Z), src[0]);
+ ureg_DP4(ureg, ureg_writemask(tmp, TGSI_WRITEMASK_W), src[0], constants[2]);
+ ureg_MOV(ureg, dst[0], ureg_src(tmp));
+
+ if (semantic_name >= 0) {
+ src[1] = ureg_DECL_vs_input(ureg, 1);
+ dst[1] = ureg_DECL_output(ureg, semantic_name, 0);
+ ureg_MOV(ureg, dst[1], src[1]);
+ }
- setup_shaders(renderer);
+ ureg_END(ureg);
- /* init vertex data that doesn't change */
- for (i = 0; i < 4; i++) {
- renderer->vertices[i][0][3] = 1.0f; /* w */
- renderer->vertices[i][1][2] = 0.0f; /* r */
- renderer->vertices[i][1][3] = 1.0f; /* q */
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+/**
+ * Set renderer vertex shader.
+ *
+ * This function modifies vertex_shader state.
+ */
+static void renderer_set_vs(struct renderer *r, RendererVs id)
+{
+ /* create as needed */
+ if (!r->cached_vs[id]) {
+ int semantic_name = -1;
+
+ switch (id) {
+ case RENDERER_VS_PLAIN:
+ break;
+ case RENDERER_VS_COLOR:
+ semantic_name = TGSI_SEMANTIC_COLOR;
+ break;
+ case RENDERER_VS_TEXTURE:
+ semantic_name = TGSI_SEMANTIC_GENERIC;
+ break;
+ default:
+ assert(!"Unknown renderer vs id");
+ break;
+ }
+
+ r->cached_vs[id] = create_passthrough_vs(r->pipe, semantic_name);
}
- return renderer;
+ cso_set_vertex_shader_handle(r->cso, r->cached_vs[id]);
}
-void renderer_destroy(struct renderer *ctx)
+/**
+ * Create a simple fragment shader that sets the depth to 0.0f.
+ */
+static void *create_scissor_fs(struct pipe_context *pipe)
+{
+ struct ureg_program *ureg;
+ struct ureg_dst out;
+ struct ureg_src imm;
+
+ ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+ out = ureg_DECL_output(ureg, TGSI_SEMANTIC_POSITION, 0);
+ imm = ureg_imm4f(ureg, 0.0f, 0.0f, 0.0f, 0.0f);
+
+ ureg_MOV(ureg, ureg_writemask(out, TGSI_WRITEMASK_Z), imm);
+ ureg_END(ureg);
+
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+/**
+ * Create a simple fragment shader that sets the color to white.
+ */
+static void *create_white_fs(struct pipe_context *pipe)
+{
+ struct ureg_program *ureg;
+ struct ureg_dst out;
+ struct ureg_src imm;
+
+ ureg = ureg_create(TGSI_PROCESSOR_FRAGMENT);
+ out = ureg_DECL_output(ureg, TGSI_SEMANTIC_COLOR, 0);
+ imm = ureg_imm4f(ureg, 1.0f, 1.0f, 1.0f, 1.0f);
+
+ ureg_MOV(ureg, out, imm);
+ ureg_END(ureg);
+
+ return ureg_create_shader_and_destroy(ureg, pipe);
+}
+
+/**
+ * Set renderer fragment shader.
+ *
+ * This function modifies fragment_shader state.
+ */
+static void renderer_set_fs(struct renderer *r, RendererFs id)
{
-#if 0
- if (ctx->fs) {
- cso_delete_fragment_shader(ctx->cso, ctx->fs);
- ctx->fs = NULL;
+ /* create as needed */
+ if (!r->cached_fs[id]) {
+ void *fs = NULL;
+
+ switch (id) {
+ case RENDERER_FS_COLOR:
+ fs = util_make_fragment_passthrough_shader(r->pipe);
+ break;
+ case RENDERER_FS_TEXTURE:
+ fs = util_make_fragment_tex_shader(r->pipe,
+ TGSI_TEXTURE_2D, TGSI_INTERPOLATE_LINEAR);
+ break;
+ case RENDERER_FS_SCISSOR:
+ fs = create_scissor_fs(r->pipe);
+ break;
+ case RENDERER_FS_WHITE:
+ fs = create_white_fs(r->pipe);
+ break;
+ default:
+ assert(!"Unknown renderer fs id");
+ break;
+ }
+
+ r->cached_fs[id] = fs;
}
-#endif
- FREE(ctx);
+
+ cso_set_fragment_shader_handle(r->cso, r->cached_fs[id]);
}
-void renderer_draw_quad(struct renderer *r,
- VGfloat x1, VGfloat y1,
- VGfloat x2, VGfloat y2,
- VGfloat depth)
+typedef enum {
+ VEGA_Y0_TOP,
+ VEGA_Y0_BOTTOM
+} VegaOrientation;
+
+static void vg_set_viewport(struct renderer *r,
+ VegaOrientation orientation)
{
- struct pipe_resource *buf;
+ const struct pipe_framebuffer_state *fb = &r->g3d.fb;
+ struct pipe_viewport_state viewport;
+ VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
+
+ viewport.scale[0] = fb->width / 2.f;
+ viewport.scale[1] = fb->height / y_scale;
+ viewport.scale[2] = 1.0;
+ viewport.scale[3] = 1.0;
+ viewport.translate[0] = fb->width / 2.f;
+ viewport.translate[1] = fb->height / 2.f;
+ viewport.translate[2] = 0.0;
+ viewport.translate[3] = 0.0;
+
+ cso_set_viewport(r->cso, &viewport);
+}
+
+/**
+ * Set renderer target.
+ *
+ * This function modifies framebuffer and viewport states.
+ */
+static void renderer_set_target(struct renderer *r,
+ struct pipe_surface *cbuf,
+ struct pipe_surface *zsbuf,
+ VGboolean y0_top)
+{
+ struct pipe_framebuffer_state fb;
+
+ memset(&fb, 0, sizeof(fb));
+ fb.width = cbuf->width;
+ fb.height = cbuf->height;
+ fb.cbufs[0] = cbuf;
+ fb.nr_cbufs = 1;
+ fb.zsbuf = zsbuf;
+ cso_set_framebuffer(r->cso, &fb);
+
+ vg_set_viewport(r, (y0_top) ? VEGA_Y0_TOP : VEGA_Y0_BOTTOM);
+}
+
+/**
+ * Set renderer blend state. Blending is disabled.
+ *
+ * This function modifies blend state.
+ */
+static void renderer_set_blend(struct renderer *r,
+ VGbitfield channel_mask)
+{
+ struct pipe_blend_state blend;
+
+ memset(&blend, 0, sizeof(blend));
+
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+
+ if (channel_mask & VG_RED)
+ blend.rt[0].colormask |= PIPE_MASK_R;
+ if (channel_mask & VG_GREEN)
+ blend.rt[0].colormask |= PIPE_MASK_G;
+ if (channel_mask & VG_BLUE)
+ blend.rt[0].colormask |= PIPE_MASK_B;
+ if (channel_mask & VG_ALPHA)
+ blend.rt[0].colormask |= PIPE_MASK_A;
+
+ cso_set_blend(r->cso, &blend);
+}
+
+/**
+ * Set renderer sampler and view states.
+ *
+ * This function modifies samplers and fragment_sampler_views states.
+ */
+static void renderer_set_samplers(struct renderer *r,
+ uint num_views,
+ struct pipe_sampler_view **views)
+{
+ struct pipe_sampler_state sampler;
+ unsigned tex_filter = PIPE_TEX_FILTER_NEAREST;
+ unsigned tex_wrap = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ uint i;
+
+ memset(&sampler, 0, sizeof(sampler));
+
+ sampler.min_img_filter = tex_filter;
+ sampler.mag_img_filter = tex_filter;
+ sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
+
+ sampler.wrap_s = tex_wrap;
+ sampler.wrap_t = tex_wrap;
+ sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+
+ sampler.normalized_coords = 1;
+
+ /* set samplers */
+ for (i = 0; i < num_views; i++)
+ cso_single_sampler(r->cso, i, &sampler);
+ cso_single_sampler_done(r->cso);
+
+ /* set views */
+ cso_set_fragment_sampler_views(r->cso, num_views, views);
+}
+
+/**
+ * Set custom renderer fragment shader, and optionally set samplers and views
+ * and upload the fragment constant buffer.
+ *
+ * This function modifies fragment_shader, samplers and fragment_sampler_views
+ * states.
+ */
+static void renderer_set_custom_fs(struct renderer *renderer,
+ void *fs,
+ const struct pipe_sampler_state **samplers,
+ struct pipe_sampler_view **views,
+ VGint num_samplers,
+ const void *const_buffer,
+ VGint const_buffer_len)
+{
+ cso_set_fragment_shader_handle(renderer->cso, fs);
+
+ /* set samplers and views */
+ if (num_samplers) {
+ cso_set_samplers(renderer->cso, num_samplers, samplers);
+ cso_set_fragment_sampler_views(renderer->cso, num_samplers, views);
+ }
+
+ /* upload fs constant buffer */
+ if (const_buffer_len) {
+ struct pipe_resource *cbuf = renderer->fs_cbuf;
+
+ if (!cbuf || renderer->fs_cbuf_len != const_buffer_len ||
+ memcmp(renderer->fs_cbuf_data, const_buffer, const_buffer_len)) {
+ pipe_resource_reference(&cbuf, NULL);
+
+ cbuf = pipe_buffer_create(renderer->pipe->screen,
+ PIPE_BIND_CONSTANT_BUFFER, const_buffer_len);
+ pipe_buffer_write(renderer->pipe, cbuf, 0,
+ const_buffer_len, const_buffer);
+ renderer->pipe->set_constant_buffer(renderer->pipe,
+ PIPE_SHADER_FRAGMENT, 0, cbuf);
+
+ renderer->fs_cbuf = cbuf;
+ if (const_buffer_len <= sizeof(renderer->fs_cbuf_data)) {
+ memcpy(renderer->fs_cbuf_data, const_buffer, const_buffer_len);
+ renderer->fs_cbuf_len = const_buffer_len;
+ }
+ else {
+ renderer->fs_cbuf_len = 0;
+ }
+ }
+ }
+}
+
+/**
+ * Setup renderer quad position.
+ */
+static void renderer_quad_pos(struct renderer *r,
+ VGfloat x0, VGfloat y0,
+ VGfloat x1, VGfloat y1,
+ VGboolean scissor)
+{
+ VGfloat z;
+
+ /* the depth test is used for scissoring */
+ z = (scissor) ? 0.0f : 1.0f;
+
+ /* positions */
+ r->vertices[0][0][0] = x0;
+ r->vertices[0][0][1] = y0;
+ r->vertices[0][0][2] = z;
- buf = setup_vertex_data(r, x1, y1, x2, y2, depth);
+ r->vertices[1][0][0] = x1;
+ r->vertices[1][0][1] = y0;
+ r->vertices[1][0][2] = z;
+ r->vertices[2][0][0] = x1;
+ r->vertices[2][0][1] = y1;
+ r->vertices[2][0][2] = z;
+
+ r->vertices[3][0][0] = x0;
+ r->vertices[3][0][1] = y1;
+ r->vertices[3][0][2] = z;
+}
+
+/**
+ * Setup renderer quad texture coordinates.
+ */
+static void renderer_quad_texcoord(struct renderer *r,
+ VGfloat x0, VGfloat y0,
+ VGfloat x1, VGfloat y1,
+ VGint tex_width, VGint tex_height)
+{
+ VGfloat s0, t0, s1, t1, r0, q0;
+ VGint i;
+
+ s0 = x0 / tex_width;
+ s1 = x1 / tex_width;
+ t0 = y0 / tex_height;
+ t1 = y1 / tex_height;
+ r0 = 0.0f;
+ q0 = 1.0f;
+
+ /* texcoords */
+ r->vertices[0][1][0] = s0;
+ r->vertices[0][1][1] = t0;
+
+ r->vertices[1][1][0] = s1;
+ r->vertices[1][1][1] = t0;
+
+ r->vertices[2][1][0] = s1;
+ r->vertices[2][1][1] = t1;
+
+ r->vertices[3][1][0] = s0;
+ r->vertices[3][1][1] = t1;
+
+ for (i = 0; i < 4; i++) {
+ r->vertices[i][1][2] = r0;
+ r->vertices[i][1][3] = q0;
+ }
+}
+
+/**
+ * Draw renderer quad.
+ */
+static void renderer_quad_draw(struct renderer *r)
+{
+ struct pipe_resource *buf;
+
+ buf = pipe_user_buffer_create(r->pipe->screen,
+ r->vertices,
+ sizeof(r->vertices),
+ PIPE_BIND_VERTEX_BUFFER);
if (buf) {
- cso_set_vertex_elements(r->cso, 2, r->owner->velems);
util_draw_vertex_buffer(r->pipe, buf, 0,
PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 2); /* attribs/vert */
+ Elements(r->vertices), /* verts */
+ Elements(r->vertices[0])); /* attribs/vert */
- pipe_resource_reference( &buf,
- NULL );
+ pipe_resource_reference(&buf, NULL);
}
}
-void renderer_draw_texture(struct renderer *r,
- struct pipe_resource *tex,
- VGfloat x1offset, VGfloat y1offset,
- VGfloat x2offset, VGfloat y2offset,
- VGfloat x1, VGfloat y1,
- VGfloat x2, VGfloat y2)
+/**
+ * Prepare the renderer for copying.
+ */
+VGboolean renderer_copy_begin(struct renderer *renderer,
+ struct pipe_surface *dst,
+ VGboolean y0_top,
+ struct pipe_sampler_view *src)
{
- struct pipe_context *pipe = r->pipe;
- struct pipe_resource *buf;
- VGfloat s0, t0, s1, t1;
+ assert(renderer->state == RENDERER_STATE_INIT);
- assert(tex->width0 != 0);
- assert(tex->height0 != 0);
+ /* sanity check */
+ if (!renderer_can_support(renderer,
+ dst->texture, PIPE_BIND_RENDER_TARGET) ||
+ !renderer_can_support(renderer,
+ src->texture, PIPE_BIND_SAMPLER_VIEW))
+ return VG_FALSE;
- s0 = x1offset / tex->width0;
- s1 = x2offset / tex->width0;
- t0 = y1offset / tex->height0;
- t1 = y2offset / tex->height0;
+ cso_save_framebuffer(renderer->cso);
+ cso_save_viewport(renderer->cso);
+ cso_save_blend(renderer->cso);
+ cso_save_samplers(renderer->cso);
+ cso_save_fragment_sampler_views(renderer->cso);
+ cso_save_fragment_shader(renderer->cso);
+ cso_save_vertex_shader(renderer->cso);
- cso_save_vertex_shader(r->cso);
- /* shaders */
- cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
+ renderer_set_target(renderer, dst, NULL, y0_top);
- /* draw quad */
- buf = setup_vertex_data_tex(r, x1, y1, x2, y2,
- s0, t0, s1, t1, 0.0f);
+ renderer_set_blend(renderer, ~0);
+ renderer_set_samplers(renderer, 1, &src);
- if (buf) {
- cso_set_vertex_elements(r->cso, 2, r->owner->velems);
- util_draw_vertex_buffer(pipe, buf, 0,
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 2); /* attribs/vert */
-
- pipe_resource_reference( &buf,
- NULL );
+ renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
+ renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
+
+ renderer_set_mvp(renderer, NULL);
+
+ /* remember the texture size */
+ renderer->u.copy.tex_width = src->texture->width0;
+ renderer->u.copy.tex_height = src->texture->height0;
+ renderer->state = RENDERER_STATE_COPY;
+
+ return VG_TRUE;
+}
+
+/**
+ * Draw into the destination rectangle given by (x, y, w, h). The texture is
+ * sampled from within the rectangle given by (sx, sy, sw, sh).
+ *
+ * The coordinates are in surface coordinates.
+ */
+void renderer_copy(struct renderer *renderer,
+ VGint x, VGint y, VGint w, VGint h,
+ VGint sx, VGint sy, VGint sw, VGint sh)
+{
+ assert(renderer->state == RENDERER_STATE_COPY);
+
+ /* there is no depth buffer for scissoring anyway */
+ renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
+ renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
+ renderer->u.copy.tex_width,
+ renderer->u.copy.tex_height);
+
+ renderer_quad_draw(renderer);
+}
+
+/**
+ * End copying and restore the states.
+ */
+void renderer_copy_end(struct renderer *renderer)
+{
+ assert(renderer->state == RENDERER_STATE_COPY);
+
+ cso_restore_framebuffer(renderer->cso);
+ cso_restore_viewport(renderer->cso);
+ cso_restore_blend(renderer->cso);
+ cso_restore_samplers(renderer->cso);
+ cso_restore_fragment_sampler_views(renderer->cso);
+ cso_restore_fragment_shader(renderer->cso);
+ cso_restore_vertex_shader(renderer->cso);
+
+ renderer->state = RENDERER_STATE_INIT;
+}
+
+/**
+ * Prepare the renderer for textured drawing.
+ */
+VGboolean renderer_drawtex_begin(struct renderer *renderer,
+ struct pipe_sampler_view *src)
+{
+ assert(renderer->state == RENDERER_STATE_INIT);
+
+ if (!renderer_can_support(renderer, src->texture, PIPE_BIND_SAMPLER_VIEW))
+ return VG_FALSE;
+
+ cso_save_blend(renderer->cso);
+ cso_save_samplers(renderer->cso);
+ cso_save_fragment_sampler_views(renderer->cso);
+ cso_save_fragment_shader(renderer->cso);
+ cso_save_vertex_shader(renderer->cso);
+
+ renderer_set_blend(renderer, ~0);
+
+ renderer_set_samplers(renderer, 1, &src);
+
+ renderer_set_fs(renderer, RENDERER_FS_TEXTURE);
+ renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
+
+ renderer_set_mvp(renderer, NULL);
+
+ /* remember the texture size */
+ renderer->u.drawtex.tex_width = src->texture->width0;
+ renderer->u.drawtex.tex_height = src->texture->height0;
+ renderer->state = RENDERER_STATE_DRAWTEX;
+
+ return VG_TRUE;
+}
+
+/**
+ * Draw into the destination rectangle given by (x, y, w, h). The texture is
+ * sampled from within the rectangle given by (sx, sy, sw, sh).
+ *
+ * The coordinates are in surface coordinates.
+ */
+void renderer_drawtex(struct renderer *renderer,
+ VGint x, VGint y, VGint w, VGint h,
+ VGint sx, VGint sy, VGint sw, VGint sh)
+{
+ assert(renderer->state == RENDERER_STATE_DRAWTEX);
+
+ /* with scissoring */
+ renderer_quad_pos(renderer, x, y, x + w, y + h, VG_TRUE);
+ renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
+ renderer->u.drawtex.tex_width,
+ renderer->u.drawtex.tex_height);
+
+ renderer_quad_draw(renderer);
+}
+
+/**
+ * End textured drawing and restore the states.
+ */
+void renderer_drawtex_end(struct renderer *renderer)
+{
+ assert(renderer->state == RENDERER_STATE_DRAWTEX);
+
+ cso_restore_blend(renderer->cso);
+ cso_restore_samplers(renderer->cso);
+ cso_restore_fragment_sampler_views(renderer->cso);
+ cso_restore_fragment_shader(renderer->cso);
+ cso_restore_vertex_shader(renderer->cso);
+
+ renderer->state = RENDERER_STATE_INIT;
+}
+
+/**
+ * Prepare the renderer for scissor update. This will reset the depth buffer
+ * to 1.0f.
+ */
+VGboolean renderer_scissor_begin(struct renderer *renderer,
+ VGboolean restore_dsa)
+{
+ struct pipe_depth_stencil_alpha_state dsa;
+
+ assert(renderer->state == RENDERER_STATE_INIT);
+
+ if (restore_dsa)
+ cso_save_depth_stencil_alpha(renderer->cso);
+ cso_save_blend(renderer->cso);
+ cso_save_fragment_shader(renderer->cso);
+
+ /* enable depth writes */
+ memset(&dsa, 0, sizeof(dsa));
+ dsa.depth.enabled = 1;
+ dsa.depth.writemask = 1;
+ dsa.depth.func = PIPE_FUNC_ALWAYS;
+ cso_set_depth_stencil_alpha(renderer->cso, &dsa);
+
+ /* disable color writes */
+ renderer_set_blend(renderer, 0);
+ renderer_set_fs(renderer, RENDERER_FS_SCISSOR);
+
+ renderer_set_mvp(renderer, NULL);
+
+ renderer->u.scissor.restore_dsa = restore_dsa;
+ renderer->state = RENDERER_STATE_SCISSOR;
+
+ /* clear the depth buffer to 1.0f */
+ renderer->pipe->clear(renderer->pipe,
+ PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0f, 0);
+
+ return VG_TRUE;
+}
+
+/**
+ * Add a scissor rectangle. Depth values inside the rectangle will be set to
+ * 0.0f.
+ */
+void renderer_scissor(struct renderer *renderer,
+ VGint x, VGint y, VGint width, VGint height)
+{
+ assert(renderer->state == RENDERER_STATE_SCISSOR);
+
+ renderer_quad_pos(renderer, x, y, x + width, y + height, VG_FALSE);
+ renderer_quad_draw(renderer);
+}
+
+/**
+ * End scissor update and restore the states.
+ */
+void renderer_scissor_end(struct renderer *renderer)
+{
+ assert(renderer->state == RENDERER_STATE_SCISSOR);
+
+ if (renderer->u.scissor.restore_dsa)
+ cso_restore_depth_stencil_alpha(renderer->cso);
+ cso_restore_blend(renderer->cso);
+ cso_restore_fragment_shader(renderer->cso);
+
+ renderer->state = RENDERER_STATE_INIT;
+}
+
+/**
+ * Prepare the renderer for clearing.
+ */
+VGboolean renderer_clear_begin(struct renderer *renderer)
+{
+ assert(renderer->state == RENDERER_STATE_INIT);
+
+ cso_save_blend(renderer->cso);
+ cso_save_fragment_shader(renderer->cso);
+ cso_save_vertex_shader(renderer->cso);
+
+ renderer_set_blend(renderer, ~0);
+ renderer_set_fs(renderer, RENDERER_FS_COLOR);
+ renderer_set_vs(renderer, RENDERER_VS_COLOR);
+
+ renderer_set_mvp(renderer, NULL);
+
+ renderer->state = RENDERER_STATE_CLEAR;
+
+ return VG_TRUE;
+}
+
+/**
+ * Clear the framebuffer with the specified region and color.
+ *
+ * The coordinates are in surface coordinates.
+ */
+void renderer_clear(struct renderer *renderer,
+ VGint x, VGint y, VGint width, VGint height,
+ const VGfloat color[4])
+{
+ VGuint i;
+
+ assert(renderer->state == RENDERER_STATE_CLEAR);
+
+ renderer_quad_pos(renderer, x, y, x + width, y + height, VG_TRUE);
+ for (i = 0; i < 4; i++)
+ memcpy(renderer->vertices[i][1], color, sizeof(VGfloat) * 4);
+
+ renderer_quad_draw(renderer);
+}
+
+/**
+ * End clearing and retore the states.
+ */
+void renderer_clear_end(struct renderer *renderer)
+{
+ assert(renderer->state == RENDERER_STATE_CLEAR);
+
+ cso_restore_blend(renderer->cso);
+ cso_restore_fragment_shader(renderer->cso);
+ cso_restore_vertex_shader(renderer->cso);
+
+ renderer->state = RENDERER_STATE_INIT;
+}
+
+/**
+ * Prepare the renderer for image filtering.
+ */
+VGboolean renderer_filter_begin(struct renderer *renderer,
+ struct pipe_resource *dst,
+ VGboolean y0_top,
+ VGbitfield channel_mask,
+ const struct pipe_sampler_state **samplers,
+ struct pipe_sampler_view **views,
+ VGint num_samplers,
+ void *fs,
+ const void *const_buffer,
+ VGint const_buffer_len)
+{
+ struct pipe_surface *surf, surf_tmpl;
+
+ assert(renderer->state == RENDERER_STATE_INIT);
+
+ if (!fs)
+ return VG_FALSE;
+ if (!renderer_can_support(renderer, dst, PIPE_BIND_RENDER_TARGET))
+ return VG_FALSE;
+
+ u_surface_default_template(&surf_tmpl, dst,
+ PIPE_BIND_RENDER_TARGET);
+ surf = renderer->pipe->create_surface(renderer->pipe, dst, &surf_tmpl);
+ if (!surf)
+ return VG_FALSE;
+
+ cso_save_framebuffer(renderer->cso);
+ cso_save_viewport(renderer->cso);
+ cso_save_blend(renderer->cso);
+
+ /* set the image as the target */
+ renderer_set_target(renderer, surf, NULL, y0_top);
+ pipe_surface_reference(&surf, NULL);
+
+ renderer_set_blend(renderer, channel_mask);
+
+ if (num_samplers) {
+ struct pipe_resource *tex;
+
+ cso_save_samplers(renderer->cso);
+ cso_save_fragment_sampler_views(renderer->cso);
+ cso_save_fragment_shader(renderer->cso);
+ cso_save_vertex_shader(renderer->cso);
+
+ renderer_set_custom_fs(renderer, fs,
+ samplers, views, num_samplers,
+ const_buffer, const_buffer_len);
+ renderer_set_vs(renderer, RENDERER_VS_TEXTURE);
+
+ tex = views[0]->texture;
+ renderer->u.filter.tex_width = tex->width0;
+ renderer->u.filter.tex_height = tex->height0;
+ renderer->u.filter.use_sampler = VG_TRUE;
}
+ else {
+ cso_save_fragment_shader(renderer->cso);
- cso_restore_vertex_shader(r->cso);
+ renderer_set_custom_fs(renderer, fs, NULL, NULL, 0,
+ const_buffer, const_buffer_len);
+
+ renderer->u.filter.use_sampler = VG_FALSE;
+ }
+
+ renderer_set_mvp(renderer, NULL);
+
+ renderer->state = RENDERER_STATE_FILTER;
+
+ return VG_TRUE;
}
-void renderer_copy_texture(struct renderer *ctx,
- struct pipe_sampler_view *src,
- VGfloat sx1, VGfloat sy1,
- VGfloat sx2, VGfloat sy2,
- struct pipe_resource *dst,
- VGfloat dx1, VGfloat dy1,
- VGfloat dx2, VGfloat dy2)
+/**
+ * Draw into a rectangle of the destination with the specified region of the
+ * texture(s).
+ *
+ * The coordinates are in surface coordinates.
+ */
+void renderer_filter(struct renderer *renderer,
+ VGint x, VGint y, VGint w, VGint h,
+ VGint sx, VGint sy, VGint sw, VGint sh)
{
- struct pipe_context *pipe = ctx->pipe;
- struct pipe_screen *screen = pipe->screen;
- struct pipe_resource *tex = src->texture;
- struct pipe_resource *buf;
- struct pipe_surface *dst_surf = screen->get_tex_surface(
- screen, dst, 0, 0, 0,
- PIPE_BIND_RENDER_TARGET);
- struct pipe_framebuffer_state fb;
- float s0, t0, s1, t1;
+ assert(renderer->state == RENDERER_STATE_FILTER);
- assert(tex->width0 != 0);
- assert(tex->height0 != 0);
- assert(dst->width0 != 0);
- assert(dst->height0 != 0);
-
-#if 0
- debug_printf("copy texture [%f, %f, %f, %f], [%f, %f, %f, %f]\n",
- sx1, sy1, sx2, sy2, dx1, dy1, dx2, dy2);
-#endif
-
-#if 1
- s0 = sx1 / tex->width0;
- s1 = sx2 / tex->width0;
- t0 = sy1 / tex->height0;
- t1 = sy2 / tex->height0;
-#else
- s0 = 0;
- s1 = 1;
- t0 = 0;
- t1 = 1;
-#endif
-
- assert(screen->is_format_supported(screen, dst_surf->format, PIPE_TEXTURE_2D,
- 0, PIPE_BIND_RENDER_TARGET, 0));
+ renderer_quad_pos(renderer, x, y, x + w, y + h, VG_FALSE);
+ if (renderer->u.filter.use_sampler) {
+ renderer_quad_texcoord(renderer, sx, sy, sx + sw, sy + sh,
+ renderer->u.filter.tex_width,
+ renderer->u.filter.tex_height);
+ }
- /* save state (restored below) */
- cso_save_blend(ctx->cso);
- cso_save_samplers(ctx->cso);
- cso_save_fragment_sampler_views(ctx->cso);
- cso_save_framebuffer(ctx->cso);
- cso_save_fragment_shader(ctx->cso);
- cso_save_vertex_shader(ctx->cso);
+ renderer_quad_draw(renderer);
+}
+
+/**
+ * End image filtering and restore the states.
+ */
+void renderer_filter_end(struct renderer *renderer)
+{
+ assert(renderer->state == RENDERER_STATE_FILTER);
- cso_save_viewport(ctx->cso);
+ if (renderer->u.filter.use_sampler) {
+ cso_restore_samplers(renderer->cso);
+ cso_restore_fragment_sampler_views(renderer->cso);
+ cso_restore_vertex_shader(renderer->cso);
+ }
+ cso_restore_framebuffer(renderer->cso);
+ cso_restore_viewport(renderer->cso);
+ cso_restore_blend(renderer->cso);
+ cso_restore_fragment_shader(renderer->cso);
- /* set misc state we care about */
- {
- struct pipe_blend_state blend;
- memset(&blend, 0, sizeof(blend));
- blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].colormask = PIPE_MASK_RGBA;
- cso_set_blend(ctx->cso, &blend);
+ renderer->state = RENDERER_STATE_INIT;
+}
+
+/**
+ * Prepare the renderer for polygon silhouette rendering.
+ */
+VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
+ struct pipe_vertex_element *velem,
+ VGFillRule rule,
+ VGboolean restore_dsa)
+{
+ struct pipe_depth_stencil_alpha_state *dsa;
+ VGboolean manual_two_sides;
+
+ assert(renderer->state == RENDERER_STATE_INIT);
+
+ cso_save_vertex_elements(renderer->cso);
+ cso_save_blend(renderer->cso);
+ cso_save_depth_stencil_alpha(renderer->cso);
+
+ cso_set_vertex_elements(renderer->cso, 1, velem);
+
+ /* disable color writes */
+ renderer_set_blend(renderer, 0);
+
+ manual_two_sides = VG_FALSE;
+ dsa = &renderer->u.polygon_stencil.dsa;
+ memset(dsa, 0, sizeof(*dsa));
+ if (rule == VG_EVEN_ODD) {
+ dsa->stencil[0].enabled = 1;
+ dsa->stencil[0].writemask = 1;
+ dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INVERT;
+ dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
+ dsa->stencil[0].valuemask = ~0;
}
+ else {
+ assert(rule == VG_NON_ZERO);
+
+ /* front face */
+ dsa->stencil[0].enabled = 1;
+ dsa->stencil[0].writemask = ~0;
+ dsa->stencil[0].fail_op = PIPE_STENCIL_OP_KEEP;
+ dsa->stencil[0].zfail_op = PIPE_STENCIL_OP_KEEP;
+ dsa->stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
+ dsa->stencil[0].func = PIPE_FUNC_ALWAYS;
+ dsa->stencil[0].valuemask = ~0;
+
+ if (renderer->pipe->screen->get_param(renderer->pipe->screen,
+ PIPE_CAP_TWO_SIDED_STENCIL)) {
+ /* back face */
+ dsa->stencil[1] = dsa->stencil[0];
+ dsa->stencil[1].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
+ }
+ else {
+ manual_two_sides = VG_TRUE;
+ }
+ }
+ cso_set_depth_stencil_alpha(renderer->cso, dsa);
+
+ if (manual_two_sides)
+ cso_save_rasterizer(renderer->cso);
- /* sampler */
- {
- struct pipe_sampler_state sampler;
- memset(&sampler, 0, sizeof(sampler));
- sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
- sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
- sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
- sampler.normalized_coords = 1;
- cso_single_sampler(ctx->cso, 0, &sampler);
- cso_single_sampler_done(ctx->cso);
+ renderer->u.polygon_stencil.manual_two_sides = manual_two_sides;
+ renderer->u.polygon_stencil.restore_dsa = restore_dsa;
+ renderer->state = RENDERER_STATE_POLYGON_STENCIL;
+
+ return VG_TRUE;
+}
+
+/**
+ * Render a polygon silhouette to stencil buffer.
+ */
+void renderer_polygon_stencil(struct renderer *renderer,
+ struct pipe_vertex_buffer *vbuf,
+ VGuint mode, VGuint start, VGuint count)
+{
+ assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
+
+ renderer->pipe->set_vertex_buffers(renderer->pipe, 1, vbuf);
+
+ if (!renderer->u.polygon_stencil.manual_two_sides) {
+ util_draw_arrays(renderer->pipe, mode, start, count);
}
+ else {
+ struct pipe_rasterizer_state raster;
+ struct pipe_depth_stencil_alpha_state dsa;
- vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
+ raster = renderer->g3d.rasterizer;
+ dsa = renderer->u.polygon_stencil.dsa;
- /* texture */
- cso_set_fragment_sampler_views(ctx->cso, 1, &src);
+ /* front */
+ raster.cull_face = PIPE_FACE_BACK;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_INCR_WRAP;
- /* shaders */
- cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
- cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
+ cso_set_rasterizer(renderer->cso, &raster);
+ cso_set_depth_stencil_alpha(renderer->cso, &dsa);
+ util_draw_arrays(renderer->pipe, mode, start, count);
- /* drawing dest */
- memset(&fb, 0, sizeof(fb));
- fb.width = dst_surf->width;
- fb.height = dst_surf->height;
- fb.nr_cbufs = 1;
- fb.cbufs[0] = dst_surf;
- {
- VGint i;
- for (i = 1; i < PIPE_MAX_COLOR_BUFS; ++i)
- fb.cbufs[i] = 0;
+ /* back */
+ raster.cull_face = PIPE_FACE_FRONT;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_DECR_WRAP;
+
+ cso_set_rasterizer(renderer->cso, &raster);
+ cso_set_depth_stencil_alpha(renderer->cso, &dsa);
+ util_draw_arrays(renderer->pipe, mode, start, count);
}
- cso_set_framebuffer(ctx->cso, &fb);
+}
+
+/**
+ * End polygon silhouette rendering.
+ */
+void renderer_polygon_stencil_end(struct renderer *renderer)
+{
+ assert(renderer->state == RENDERER_STATE_POLYGON_STENCIL);
- /* draw quad */
- buf = setup_vertex_data_tex(ctx,
- dx1, dy1,
- dx2, dy2,
- s0, t0, s1, t1,
- 0.0f);
+ if (renderer->u.polygon_stencil.manual_two_sides)
+ cso_restore_rasterizer(renderer->cso);
- if (buf) {
- cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems);
- util_draw_vertex_buffer(ctx->pipe, buf, 0,
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 2); /* attribs/vert */
+ cso_restore_vertex_elements(renderer->cso);
+
+ /* restore color writes */
+ cso_restore_blend(renderer->cso);
+
+ if (renderer->u.polygon_stencil.restore_dsa)
+ cso_restore_depth_stencil_alpha(renderer->cso);
+
+ renderer->state = RENDERER_STATE_INIT;
+}
+
+/**
+ * Prepare the renderer for polygon filling.
+ */
+VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
+ VGboolean save_dsa)
+{
+ struct pipe_depth_stencil_alpha_state dsa;
+
+ assert(renderer->state == RENDERER_STATE_INIT);
+
+ if (save_dsa)
+ cso_save_depth_stencil_alpha(renderer->cso);
+
+ /* setup stencil ops */
+ memset(&dsa, 0, sizeof(dsa));
+ dsa.stencil[0].enabled = 1;
+ dsa.stencil[0].func = PIPE_FUNC_NOTEQUAL;
+ dsa.stencil[0].fail_op = PIPE_STENCIL_OP_REPLACE;
+ dsa.stencil[0].zfail_op = PIPE_STENCIL_OP_REPLACE;
+ dsa.stencil[0].zpass_op = PIPE_STENCIL_OP_REPLACE;
+ dsa.stencil[0].valuemask = ~0;
+ dsa.stencil[0].writemask = ~0;
+ dsa.depth = renderer->g3d.dsa.depth;
+ cso_set_depth_stencil_alpha(renderer->cso, &dsa);
+
+ renderer->state = RENDERER_STATE_POLYGON_FILL;
+
+ return VG_TRUE;
+}
+
+/**
+ * Fill a polygon.
+ */
+void renderer_polygon_fill(struct renderer *renderer,
+ VGfloat min_x, VGfloat min_y,
+ VGfloat max_x, VGfloat max_y)
+{
+ assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
+
+ renderer_quad_pos(renderer, min_x, min_y, max_x, max_y, VG_TRUE);
+ renderer_quad_draw(renderer);
+}
+
+/**
+ * End polygon filling.
+ */
+void renderer_polygon_fill_end(struct renderer *renderer)
+{
+ assert(renderer->state == RENDERER_STATE_POLYGON_FILL);
+
+ cso_restore_depth_stencil_alpha(renderer->cso);
- pipe_resource_reference( &buf,
- NULL );
+ renderer->state = RENDERER_STATE_INIT;
+}
+
+struct renderer * renderer_create(struct vg_context *owner)
+{
+ struct renderer *renderer;
+ struct pipe_rasterizer_state *raster;
+ struct pipe_stencil_ref sr;
+ VGint i;
+
+ renderer = CALLOC_STRUCT(renderer);
+ if (!renderer)
+ return NULL;
+
+ renderer->pipe = owner->pipe;
+ renderer->cso = owner->cso_context;
+
+ /* init vertex data that doesn't change */
+ for (i = 0; i < 4; i++)
+ renderer->vertices[i][0][3] = 1.0f; /* w */
+
+ for (i = 0; i < 2; i++) {
+ renderer->velems[i].src_offset = i * 4 * sizeof(float);
+ renderer->velems[i].instance_divisor = 0;
+ renderer->velems[i].vertex_buffer_index = 0;
+ renderer->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
+ }
+ cso_set_vertex_elements(renderer->cso, 2, renderer->velems);
+
+ /* GL rasterization rules */
+ raster = &renderer->g3d.rasterizer;
+ memset(raster, 0, sizeof(*raster));
+ raster->gl_rasterization_rules = 1;
+ cso_set_rasterizer(renderer->cso, raster);
+
+ /* fixed at 0 */
+ memset(&sr, 0, sizeof(sr));
+ cso_set_stencil_ref(renderer->cso, &sr);
+
+ renderer_set_vs(renderer, RENDERER_VS_PLAIN);
+
+ renderer->state = RENDERER_STATE_INIT;
+
+ return renderer;
+}
+
+void renderer_destroy(struct renderer *ctx)
+{
+ int i;
+
+ for (i = 0; i < NUM_RENDERER_VS; i++) {
+ if (ctx->cached_vs[i])
+ cso_delete_vertex_shader(ctx->cso, ctx->cached_vs[i]);
+ }
+ for (i = 0; i < NUM_RENDERER_FS; i++) {
+ if (ctx->cached_fs[i])
+ cso_delete_fragment_shader(ctx->cso, ctx->cached_fs[i]);
+ }
+
+ pipe_resource_reference(&ctx->vs_cbuf, NULL);
+ pipe_resource_reference(&ctx->fs_cbuf, NULL);
+
+ FREE(ctx);
+}
+
+static void update_clip_state(struct renderer *renderer,
+ const struct vg_state *state)
+{
+ struct pipe_depth_stencil_alpha_state *dsa = &renderer->g3d.dsa;
+
+ memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
+
+ if (state->scissoring) {
+ struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
+ int i;
+
+ renderer_scissor_begin(renderer, VG_FALSE);
+
+ for (i = 0; i < state->scissor_rects_num; ++i) {
+ const float x = state->scissor_rects[i * 4 + 0].f;
+ const float y = state->scissor_rects[i * 4 + 1].f;
+ const float width = state->scissor_rects[i * 4 + 2].f;
+ const float height = state->scissor_rects[i * 4 + 3].f;
+ VGint x0, y0, x1, y1, iw, ih;
+
+ x0 = (VGint) x;
+ y0 = (VGint) y;
+ if (x0 < 0)
+ x0 = 0;
+ if (y0 < 0)
+ y0 = 0;
+
+ /* note that x1 and y1 are exclusive */
+ x1 = (VGint) ceilf(x + width);
+ y1 = (VGint) ceilf(y + height);
+ if (x1 > fb->width)
+ x1 = fb->width;
+ if (y1 > fb->height)
+ y1 = fb->height;
+
+ iw = x1 - x0;
+ ih = y1 - y0;
+ if (iw > 0 && ih> 0 )
+ renderer_scissor(renderer, x0, y0, iw, ih);
+ }
+
+ renderer_scissor_end(renderer);
+
+ dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
+ dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
+ dsa->depth.func = PIPE_FUNC_GEQUAL;
}
+}
+
+static void renderer_validate_blend(struct renderer *renderer,
+ const struct vg_state *state,
+ enum pipe_format fb_format)
+{
+ struct pipe_blend_state blend;
+
+ memset(&blend, 0, sizeof(blend));
+ blend.rt[0].colormask = PIPE_MASK_RGBA;
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- /* restore state we changed */
- cso_restore_blend(ctx->cso);
- cso_restore_samplers(ctx->cso);
- cso_restore_fragment_sampler_views(ctx->cso);
- cso_restore_framebuffer(ctx->cso);
- cso_restore_vertex_shader(ctx->cso);
- cso_restore_fragment_shader(ctx->cso);
- cso_restore_viewport(ctx->cso);
+ /* TODO alpha masking happens after blending? */
+
+ switch (state->blend_mode) {
+ case VG_BLEND_SRC:
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ break;
+ case VG_BLEND_SRC_OVER:
+ if (!util_format_has_alpha(fb_format)) {
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
+ blend.rt[0].blend_enable = 1;
+ }
+ break;
+ case VG_BLEND_SRC_IN:
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].blend_enable = 1;
+ break;
+ case VG_BLEND_DST_IN:
+ blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
+ blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
+ blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
+ blend.rt[0].blend_enable = 1;
+ break;
+ case VG_BLEND_DST_OVER:
+ case VG_BLEND_MULTIPLY:
+ case VG_BLEND_SCREEN:
+ case VG_BLEND_DARKEN:
+ case VG_BLEND_LIGHTEN:
+ case VG_BLEND_ADDITIVE:
+ /* need a shader */
+ break;
+ default:
+ assert(!"not implemented blend mode");
+ break;
+ }
- pipe_surface_reference(&dst_surf, NULL);
+ cso_set_blend(renderer->cso, &blend);
+}
+
+/**
+ * Propogate OpenVG state changes to the renderer. Only framebuffer, blending
+ * and scissoring states are relevant here.
+ */
+void renderer_validate(struct renderer *renderer,
+ VGbitfield dirty,
+ const struct st_framebuffer *stfb,
+ const struct vg_state *state)
+{
+ assert(renderer->state == RENDERER_STATE_INIT);
+
+ dirty |= renderer->dirty;
+ renderer->dirty = 0;
+
+ if (dirty & FRAMEBUFFER_DIRTY) {
+ struct pipe_framebuffer_state *fb = &renderer->g3d.fb;
+ struct matrix *proj = &renderer->projection;
+
+ memset(fb, 0, sizeof(struct pipe_framebuffer_state));
+ fb->width = stfb->width;
+ fb->height = stfb->height;
+ fb->nr_cbufs = 1;
+ fb->cbufs[0] = stfb->strb->surface;
+ fb->zsbuf = stfb->dsrb->surface;
+
+ cso_set_framebuffer(renderer->cso, fb);
+ vg_set_viewport(renderer, VEGA_Y0_BOTTOM);
+
+ matrix_load_identity(proj);
+ matrix_translate(proj, -1.0f, -1.0f);
+ matrix_scale(proj, 2.0f / fb->width, 2.0f / fb->height);
+
+ /* we also got a new depth buffer */
+ if (dirty & DEPTH_STENCIL_DIRTY) {
+ renderer->pipe->clear(renderer->pipe,
+ PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
+ }
+ }
+
+ /* must be last because it renders to the depth buffer*/
+ if (dirty & DEPTH_STENCIL_DIRTY) {
+ update_clip_state(renderer, state);
+ cso_set_depth_stencil_alpha(renderer->cso, &renderer->g3d.dsa);
+ }
+
+ if (dirty & BLEND_DIRTY)
+ renderer_validate_blend(renderer, state, stfb->strb->format);
+}
+
+/**
+ * Prepare the renderer for OpenVG pipeline.
+ */
+void renderer_validate_for_shader(struct renderer *renderer,
+ const struct pipe_sampler_state **samplers,
+ struct pipe_sampler_view **views,
+ VGint num_samplers,
+ const struct matrix *modelview,
+ void *fs,
+ const void *const_buffer,
+ VGint const_buffer_len)
+{
+ struct matrix mvp = renderer->projection;
+
+ /* will be used in POLYGON_STENCIL and POLYGON_FILL */
+ matrix_mult(&mvp, modelview);
+ renderer_set_mvp(renderer, &mvp);
+
+ renderer_set_custom_fs(renderer, fs,
+ samplers, views, num_samplers,
+ const_buffer, const_buffer_len);
+}
+
+void renderer_validate_for_mask_rendering(struct renderer *renderer,
+ struct pipe_surface *dst,
+ const struct matrix *modelview)
+{
+ struct matrix mvp = renderer->projection;
+
+ /* will be used in POLYGON_STENCIL and POLYGON_FILL */
+ matrix_mult(&mvp, modelview);
+ renderer_set_mvp(renderer, &mvp);
+
+ renderer_set_target(renderer, dst, renderer->g3d.fb.zsbuf, VG_FALSE);
+ renderer_set_blend(renderer, ~0);
+ renderer_set_fs(renderer, RENDERER_FS_WHITE);
+
+ /* set internal dirty flags (hacky!) */
+ renderer->dirty = FRAMEBUFFER_DIRTY | BLEND_DIRTY;
}
void renderer_copy_surface(struct renderer *ctx,
@@ -409,13 +1429,11 @@ void renderer_copy_surface(struct renderer *ctx,
{
struct pipe_context *pipe = ctx->pipe;
struct pipe_screen *screen = pipe->screen;
- struct pipe_resource *buf;
struct pipe_sampler_view view_templ;
struct pipe_sampler_view *view;
+ struct pipe_box src_box;
struct pipe_resource texTemp, *tex;
- struct pipe_subresource subsrc, subdst;
- struct pipe_framebuffer_state fb;
- struct st_framebuffer *stfb = ctx->owner->draw_buffer;
+ const struct pipe_framebuffer_state *fb = &ctx->g3d.fb;
const int srcW = abs(srcX1 - srcX0);
const int srcH = abs(srcY1 - srcY0);
const int srcLeft = MIN2(srcX0, srcX1);
@@ -458,6 +1476,7 @@ void renderer_copy_surface(struct renderer *ctx,
texTemp.width0 = srcW;
texTemp.height0 = srcH;
texTemp.depth0 = 1;
+ texTemp.array_size = 1;
texTemp.bind = PIPE_BIND_SAMPLER_VIEW;
tex = screen->resource_create(screen, &texTemp);
@@ -470,100 +1489,35 @@ void renderer_copy_surface(struct renderer *ctx,
if (!view)
return;
- subdst.face = 0;
- subdst.level = 0;
- subsrc.face = src->face;
- subsrc.level = src->level;
+ u_box_2d_zslice(srcLeft, srcTop, src->u.tex.first_layer, srcW, srcH, &src_box);
pipe->resource_copy_region(pipe,
- tex, subdst, 0, 0, 0, /* dest */
- src->texture, subsrc, srcLeft, srcTop, src->zslice, /* src */
- srcW, srcH); /* size */
-
- /* save state (restored below) */
- cso_save_blend(ctx->cso);
- cso_save_samplers(ctx->cso);
- cso_save_fragment_sampler_views(ctx->cso);
- cso_save_framebuffer(ctx->cso);
- cso_save_fragment_shader(ctx->cso);
- cso_save_vertex_shader(ctx->cso);
- cso_save_viewport(ctx->cso);
-
- /* set misc state we care about */
- {
- struct pipe_blend_state blend;
- memset(&blend, 0, sizeof(blend));
- blend.rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend.rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend.rt[0].colormask = PIPE_MASK_RGBA;
- cso_set_blend(ctx->cso, &blend);
+ tex, 0, 0, 0, 0, /* dest */
+ src->texture, 0, &src_box);
+
+ assert(floatsEqual(z, 0.0f));
+
+ /* draw */
+ if (fb->cbufs[0] == dst) {
+ /* transform back to surface coordinates */
+ dstY0 = dst->height - dstY0;
+ dstY1 = dst->height - dstY1;
+
+ if (renderer_drawtex_begin(ctx, view)) {
+ renderer_drawtex(ctx,
+ dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
+ 0, 0, view->texture->width0, view->texture->height0);
+ renderer_drawtex_end(ctx);
+ }
}
-
- vg_set_viewport(ctx->owner, VEGA_Y0_TOP);
-
- /* sampler */
- {
- struct pipe_sampler_state sampler;
- memset(&sampler, 0, sizeof(sampler));
- sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
- sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
- sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
- sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
- sampler.normalized_coords = 1;
- cso_single_sampler(ctx->cso, 0, &sampler);
- cso_single_sampler_done(ctx->cso);
- }
-
- /* texture */
- cso_set_fragment_sampler_views(ctx->cso, 1, &view);
-
- /* shaders */
- cso_set_fragment_shader_handle(ctx->cso, ctx->fs);
- cso_set_vertex_shader_handle(ctx->cso, vg_texture_vs(ctx->owner));
-
- /* drawing dest */
- if (stfb->strb->surface != dst) {
- memset(&fb, 0, sizeof(fb));
- fb.width = dst->width;
- fb.height = dst->height;
- fb.nr_cbufs = 1;
- fb.cbufs[0] = dst;
- fb.zsbuf = stfb->dsrb->surface;
- cso_set_framebuffer(ctx->cso, &fb);
+ else {
+ if (renderer_copy_begin(ctx, dst, VG_TRUE, view)) {
+ renderer_copy(ctx,
+ dstX0, dstY0, dstX1 - dstX0, dstY1 - dstY0,
+ 0, 0, view->texture->width0, view->texture->height0);
+ renderer_copy_end(ctx);
+ }
}
-
- /* draw quad */
- buf = setup_vertex_data(ctx,
- (float) dstX0, (float) dstY0,
- (float) dstX1, (float) dstY1, z);
-
- if (buf) {
- cso_set_vertex_elements(ctx->cso, 2, ctx->owner->velems);
- util_draw_vertex_buffer(ctx->pipe, buf, 0,
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 2); /* attribs/vert */
-
- pipe_resource_reference( &buf,
- NULL );
- }
-
-
- /* restore state we changed */
- cso_restore_blend(ctx->cso);
- cso_restore_samplers(ctx->cso);
- cso_restore_fragment_sampler_views(ctx->cso);
- cso_restore_framebuffer(ctx->cso);
- cso_restore_fragment_shader(ctx->cso);
- cso_restore_vertex_shader(ctx->cso);
- cso_restore_viewport(ctx->cso);
-
- pipe_resource_reference(&tex, NULL);
- pipe_sampler_view_reference(&view, NULL);
}
void renderer_texture_quad(struct renderer *r,
@@ -575,36 +1529,38 @@ void renderer_texture_quad(struct renderer *r,
VGfloat x3, VGfloat y3,
VGfloat x4, VGfloat y4)
{
- struct pipe_context *pipe = r->pipe;
- struct pipe_resource *buf;
- VGfloat s0, t0, s1, t1;
+ const VGfloat z = 0.0f;
+ assert(r->state == RENDERER_STATE_INIT);
assert(tex->width0 != 0);
assert(tex->height0 != 0);
- s0 = x1offset / tex->width0;
- s1 = x2offset / tex->width0;
- t0 = y1offset / tex->height0;
- t1 = y2offset / tex->height0;
-
cso_save_vertex_shader(r->cso);
- /* shaders */
- cso_set_vertex_shader_handle(r->cso, vg_texture_vs(r->owner));
- /* draw quad */
- buf = setup_vertex_data_qtex(r, x1, y1, x2, y2, x3, y3, x4, y4,
- s0, t0, s1, t1, 0.0f);
+ renderer_set_vs(r, RENDERER_VS_TEXTURE);
- if (buf) {
- cso_set_vertex_elements(r->cso, 2, r->owner->velems);
- util_draw_vertex_buffer(pipe, buf, 0,
- PIPE_PRIM_TRIANGLE_FAN,
- 4, /* verts */
- 2); /* attribs/vert */
+ /* manually set up positions */
+ r->vertices[0][0][0] = x1;
+ r->vertices[0][0][1] = y1;
+ r->vertices[0][0][2] = z;
- pipe_resource_reference(&buf,
- NULL);
- }
+ r->vertices[1][0][0] = x2;
+ r->vertices[1][0][1] = y2;
+ r->vertices[1][0][2] = z;
+
+ r->vertices[2][0][0] = x3;
+ r->vertices[2][0][1] = y3;
+ r->vertices[2][0][2] = z;
+
+ r->vertices[3][0][0] = x4;
+ r->vertices[3][0][1] = y4;
+ r->vertices[3][0][2] = z;
+
+ /* texcoords */
+ renderer_quad_texcoord(r, x1offset, y1offset,
+ x2offset, y2offset, tex->width0, tex->height0);
+
+ renderer_quad_draw(r);
cso_restore_vertex_shader(r->cso);
}
diff --git a/src/gallium/state_trackers/vega/renderer.h b/src/gallium/state_trackers/vega/renderer.h
index b1a9fb58be6..fe719936580 100644
--- a/src/gallium/state_trackers/vega/renderer.h
+++ b/src/gallium/state_trackers/vega/renderer.h
@@ -1,6 +1,7 @@
/**************************************************************************
*
* Copyright 2009 VMware, Inc. All Rights Reserved.
+ * Copyright 2010 LunarG, Inc. All Rights Reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a
* copy of this software and associated documentation files (the
@@ -32,23 +33,110 @@
struct renderer;
struct vg_context;
+struct vg_state;
+struct st_framebuffer;
struct pipe_resource;
+struct pipe_sampler_state;
struct pipe_sampler_view;
struct pipe_surface;
+struct pipe_vertex_element;
+struct pipe_vertex_buffer;
+struct matrix;
struct renderer *renderer_create(struct vg_context *owner);
void renderer_destroy(struct renderer *);
-void renderer_draw_quad(struct renderer *,
- VGfloat x1, VGfloat y1,
- VGfloat x2, VGfloat y2,
- VGfloat depth);
-void renderer_draw_texture(struct renderer *,
- struct pipe_resource *texture,
- VGfloat x1offset, VGfloat y1offset,
- VGfloat x2offset, VGfloat y2offset,
- VGfloat x1, VGfloat y1,
- VGfloat x2, VGfloat y2);
+void renderer_validate(struct renderer *renderer,
+ VGbitfield dirty,
+ const struct st_framebuffer *stfb,
+ const struct vg_state *state);
+
+void renderer_validate_for_shader(struct renderer *renderer,
+ const struct pipe_sampler_state **samplers,
+ struct pipe_sampler_view **views,
+ VGint num_samplers,
+ const struct matrix *modelview,
+ void *fs,
+ const void *const_buffer,
+ VGint const_buffer_len);
+
+void renderer_validate_for_mask_rendering(struct renderer *renderer,
+ struct pipe_surface *dst,
+ const struct matrix *modelview);
+
+VGboolean renderer_copy_begin(struct renderer *renderer,
+ struct pipe_surface *dst,
+ VGboolean y0_top,
+ struct pipe_sampler_view *src);
+
+void renderer_copy(struct renderer *renderer,
+ VGint x, VGint y, VGint w, VGint h,
+ VGint sx, VGint sy, VGint sw, VGint sh);
+
+void renderer_copy_end(struct renderer *renderer);
+
+VGboolean renderer_drawtex_begin(struct renderer *renderer,
+ struct pipe_sampler_view *src);
+
+void renderer_drawtex(struct renderer *renderer,
+ VGint x, VGint y, VGint w, VGint h,
+ VGint sx, VGint sy, VGint sw, VGint sh);
+
+void renderer_drawtex_end(struct renderer *renderer);
+
+VGboolean renderer_scissor_begin(struct renderer *renderer,
+ VGboolean restore_dsa);
+
+void renderer_scissor(struct renderer *renderer,
+ VGint x, VGint y, VGint width, VGint height);
+
+void renderer_scissor_end(struct renderer *renderer);
+
+VGboolean renderer_clear_begin(struct renderer *renderer);
+
+void renderer_clear(struct renderer *renderer,
+ VGint x, VGint y, VGint width, VGint height,
+ const VGfloat color[4]);
+
+void renderer_clear_end(struct renderer *renderer);
+
+VGboolean renderer_filter_begin(struct renderer *renderer,
+ struct pipe_resource *dst,
+ VGboolean y0_top,
+ VGbitfield channel_mask,
+ const struct pipe_sampler_state **samplers,
+ struct pipe_sampler_view **views,
+ VGint num_samplers,
+ void *fs,
+ const void *const_buffer,
+ VGint const_buffer_len);
+
+void renderer_filter(struct renderer *renderer,
+ VGint x, VGint y, VGint w, VGint h,
+ VGint sx, VGint sy, VGint sw, VGint sh);
+
+void renderer_filter_end(struct renderer *renderer);
+
+VGboolean renderer_polygon_stencil_begin(struct renderer *renderer,
+ struct pipe_vertex_element *velem,
+ VGFillRule rule,
+ VGboolean restore_dsa);
+
+void renderer_polygon_stencil(struct renderer *renderer,
+ struct pipe_vertex_buffer *vbuf,
+ VGuint mode, VGuint start, VGuint count);
+
+void renderer_polygon_stencil_end(struct renderer *renderer);
+
+VGboolean renderer_polygon_fill_begin(struct renderer *renderer,
+ VGboolean save_dsa);
+
+void renderer_polygon_fill(struct renderer *renderer,
+ VGfloat min_x, VGfloat min_y,
+ VGfloat max_x, VGfloat max_y);
+
+void renderer_polygon_fill_end(struct renderer *renderer);
+
void renderer_texture_quad(struct renderer *,
struct pipe_resource *texture,
VGfloat x1offset, VGfloat y1offset,
@@ -57,13 +145,7 @@ void renderer_texture_quad(struct renderer *,
VGfloat x2, VGfloat y2,
VGfloat x3, VGfloat y3,
VGfloat x4, VGfloat y4);
-void renderer_copy_texture(struct renderer *r,
- struct pipe_sampler_view *src,
- VGfloat sx1, VGfloat sy1,
- VGfloat sx2, VGfloat sy2,
- struct pipe_resource *dst,
- VGfloat dx1, VGfloat dy1,
- VGfloat dx2, VGfloat dy2);
+
void renderer_copy_surface(struct renderer *r,
struct pipe_surface *src,
int sx1, int sy1,
diff --git a/src/gallium/state_trackers/vega/shader.c b/src/gallium/state_trackers/vega/shader.c
index eab1349639c..0ed721376cf 100644
--- a/src/gallium/state_trackers/vega/shader.c
+++ b/src/gallium/state_trackers/vega/shader.c
@@ -31,22 +31,29 @@
#include "paint.h"
#include "mask.h"
#include "image.h"
+#include "renderer.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "pipe/p_state.h"
#include "util/u_inlines.h"
#include "util/u_memory.h"
+#include "util/u_math.h"
+#include "util/u_format.h"
-#define MAX_CONSTANTS 20
+#define MAX_CONSTANTS 28
struct shader {
struct vg_context *context;
+ VGboolean color_transform;
VGboolean masking;
struct vg_paint *paint;
struct vg_image *image;
+ struct matrix modelview;
+ struct matrix paint_matrix;
+
VGboolean drawing_image;
VGImageMode image_mode;
@@ -71,6 +78,11 @@ void shader_destroy(struct shader *shader)
FREE(shader);
}
+void shader_set_color_transform(struct shader *shader, VGboolean set)
+{
+ shader->color_transform = set;
+}
+
void shader_set_masking(struct shader *shader, VGboolean set)
{
shader->masking = set;
@@ -91,49 +103,64 @@ struct vg_paint * shader_paint(struct shader *shader)
return shader->paint;
}
-
-static void setup_constant_buffer(struct shader *shader)
+static VGint setup_constant_buffer(struct shader *shader)
{
- struct vg_context *ctx = shader->context;
- struct pipe_context *pipe = shader->context->pipe;
- struct pipe_resource **cbuf = &shader->cbuf;
+ const struct vg_state *state = &shader->context->state.vg;
VGint param_bytes = paint_constant_buffer_size(shader->paint);
- float temp_buf[MAX_CONSTANTS];
+ VGint i;
+
+ param_bytes += sizeof(VGfloat) * 8;
+ assert(param_bytes <= sizeof(shader->constants));
+
+ if (state->color_transform) {
+ for (i = 0; i < 8; i++) {
+ VGfloat val = (i < 4) ? 127.0f : 1.0f;
+ shader->constants[i] =
+ CLAMP(state->color_transform_values[i], -val, val);
+ }
+ }
+ else {
+ memset(shader->constants, 0, sizeof(VGfloat) * 8);
+ }
- assert(param_bytes <= sizeof(temp_buf));
- paint_fill_constant_buffer(shader->paint, temp_buf);
+ paint_fill_constant_buffer(shader->paint,
+ &shader->paint_matrix, shader->constants + 8);
- if (*cbuf == NULL ||
- memcmp(temp_buf, shader->constants, param_bytes) != 0)
- {
- pipe_resource_reference(cbuf, NULL);
+ return param_bytes;
+}
+
+static VGboolean blend_use_shader(struct vg_context *ctx)
+{
+ VGboolean advanced_blending;
- memcpy(shader->constants, temp_buf, param_bytes);
- *cbuf = pipe_user_buffer_create(pipe->screen,
- &shader->constants,
- sizeof(shader->constants),
- PIPE_BIND_VERTEX_BUFFER);
+ switch (ctx->state.vg.blend_mode) {
+ case VG_BLEND_SRC_OVER:
+ advanced_blending =
+ util_format_has_alpha(ctx->draw_buffer->strb->format);
+ break;
+ case VG_BLEND_DST_OVER:
+ case VG_BLEND_MULTIPLY:
+ case VG_BLEND_SCREEN:
+ case VG_BLEND_DARKEN:
+ case VG_BLEND_LIGHTEN:
+ case VG_BLEND_ADDITIVE:
+ advanced_blending = VG_TRUE;
+ break;
+ default:
+ advanced_blending = VG_FALSE;
+ break;
}
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_FRAGMENT, 0, *cbuf);
+ return advanced_blending;
}
static VGint blend_bind_samplers(struct vg_context *ctx,
struct pipe_sampler_state **samplers,
struct pipe_sampler_view **sampler_views)
{
- VGBlendMode bmode = ctx->state.vg.blend_mode;
-
- if (bmode == VG_BLEND_MULTIPLY ||
- bmode == VG_BLEND_SCREEN ||
- bmode == VG_BLEND_DARKEN ||
- bmode == VG_BLEND_LIGHTEN) {
- struct st_framebuffer *stfb = ctx->draw_buffer;
-
- vg_prepare_blend_surface(ctx);
-
+ if (blend_use_shader(ctx)) {
samplers[2] = &ctx->blend_sampler;
- sampler_views[2] = stfb->blend_texture_view;
+ sampler_views[2] = vg_prepare_blend_surface(ctx);
if (!samplers[0] || !sampler_views[0]) {
samplers[0] = samplers[2];
@@ -149,10 +176,10 @@ static VGint blend_bind_samplers(struct vg_context *ctx,
return 0;
}
-static void setup_samplers(struct shader *shader)
+static VGint setup_samplers(struct shader *shader,
+ struct pipe_sampler_state **samplers,
+ struct pipe_sampler_view **sampler_views)
{
- struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
- struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
struct vg_context *ctx = shader->context;
/* a little wonky: we use the num as a boolean that just says
* whether any sampler/textures have been set. the actual numbering
@@ -179,10 +206,7 @@ static void setup_samplers(struct shader *shader)
if (shader->drawing_image && shader->image)
num += image_bind_samplers(shader->image, samplers, sampler_views);
- if (num) {
- cso_set_samplers(ctx->cso_context, 4, (const struct pipe_sampler_state **)samplers);
- cso_set_fragment_sampler_views(ctx->cso_context, 4, sampler_views);
- }
+ return (num) ? 4 : 0;
}
static INLINE VGboolean is_format_bw(struct shader *shader)
@@ -227,6 +251,9 @@ static void setup_shader_program(struct shader *shader)
default:
abort();
}
+
+ if (paint_is_degenerate(shader->paint))
+ shader_id = VEGA_PAINT_DEGENERATE_SHADER;
}
/* second stage image */
@@ -246,43 +273,86 @@ static void setup_shader_program(struct shader *shader)
}
}
- if (shader->masking)
- shader_id |= VEGA_MASK_SHADER;
+ if (shader->color_transform)
+ shader_id |= VEGA_COLOR_TRANSFORM_SHADER;
- switch(blend_mode) {
- case VG_BLEND_MULTIPLY:
- shader_id |= VEGA_BLEND_MULTIPLY_SHADER;
- break;
- case VG_BLEND_SCREEN:
- shader_id |= VEGA_BLEND_SCREEN_SHADER;
- break;
- case VG_BLEND_DARKEN:
- shader_id |= VEGA_BLEND_DARKEN_SHADER;
- break;
- case VG_BLEND_LIGHTEN:
- shader_id |= VEGA_BLEND_LIGHTEN_SHADER;
- break;
- default:
- /* handled by pipe_blend_state */
- break;
+ if (blend_use_shader(ctx)) {
+ if (shader->drawing_image && shader->image_mode == VG_DRAW_IMAGE_STENCIL)
+ shader_id |= VEGA_ALPHA_PER_CHANNEL_SHADER;
+ else
+ shader_id |= VEGA_ALPHA_NORMAL_SHADER;
+
+ switch(blend_mode) {
+ case VG_BLEND_SRC:
+ shader_id |= VEGA_BLEND_SRC_SHADER;
+ break;
+ case VG_BLEND_SRC_OVER:
+ shader_id |= VEGA_BLEND_SRC_OVER_SHADER;
+ break;
+ case VG_BLEND_DST_OVER:
+ shader_id |= VEGA_BLEND_DST_OVER_SHADER;
+ break;
+ case VG_BLEND_SRC_IN:
+ shader_id |= VEGA_BLEND_SRC_IN_SHADER;
+ break;
+ case VG_BLEND_DST_IN:
+ shader_id |= VEGA_BLEND_DST_IN_SHADER;
+ break;
+ case VG_BLEND_MULTIPLY:
+ shader_id |= VEGA_BLEND_MULTIPLY_SHADER;
+ break;
+ case VG_BLEND_SCREEN:
+ shader_id |= VEGA_BLEND_SCREEN_SHADER;
+ break;
+ case VG_BLEND_DARKEN:
+ shader_id |= VEGA_BLEND_DARKEN_SHADER;
+ break;
+ case VG_BLEND_LIGHTEN:
+ shader_id |= VEGA_BLEND_LIGHTEN_SHADER;
+ break;
+ case VG_BLEND_ADDITIVE:
+ shader_id |= VEGA_BLEND_ADDITIVE_SHADER;
+ break;
+ default:
+ assert(0);
+ break;
+ }
+ }
+ else {
+ /* update alpha of the source */
+ if (shader->drawing_image && shader->image_mode == VG_DRAW_IMAGE_STENCIL)
+ shader_id |= VEGA_ALPHA_PER_CHANNEL_SHADER;
}
+ if (shader->masking)
+ shader_id |= VEGA_MASK_SHADER;
+
if (black_white)
shader_id |= VEGA_BW_SHADER;
shader->fs = shaders_cache_fill(ctx->sc, shader_id);
- cso_set_fragment_shader_handle(ctx->cso_context, shader->fs);
}
void shader_bind(struct shader *shader)
{
+ struct vg_context *ctx = shader->context;
+ struct pipe_sampler_state *samplers[PIPE_MAX_SAMPLERS];
+ struct pipe_sampler_view *sampler_views[PIPE_MAX_SAMPLERS];
+ VGint num_samplers, param_bytes;
+
/* first resolve the real paint type */
paint_resolve_type(shader->paint);
- setup_constant_buffer(shader);
- setup_samplers(shader);
+ num_samplers = setup_samplers(shader, samplers, sampler_views);
+ param_bytes = setup_constant_buffer(shader);
setup_shader_program(shader);
+
+ renderer_validate_for_shader(ctx->renderer,
+ (const struct pipe_sampler_state **) samplers,
+ sampler_views, num_samplers,
+ &shader->modelview,
+ shader->fs, (const void *) shader->constants, param_bytes);
}
void shader_set_image_mode(struct shader *shader, VGImageMode image_mode)
@@ -309,3 +379,28 @@ void shader_set_image(struct shader *shader, struct vg_image *img)
{
shader->image = img;
}
+
+/**
+ * Set the transformation to map a vertex to the surface coordinates.
+ */
+void shader_set_surface_matrix(struct shader *shader,
+ const struct matrix *mat)
+{
+ shader->modelview = *mat;
+}
+
+/**
+ * Set the transformation to map a pixel to the paint coordinates.
+ */
+void shader_set_paint_matrix(struct shader *shader, const struct matrix *mat)
+{
+ const struct st_framebuffer *stfb = shader->context->draw_buffer;
+ const VGfloat px_center_offset = 0.5f;
+
+ memcpy(&shader->paint_matrix, mat, sizeof(*mat));
+
+ /* make it window-to-paint for the shaders */
+ matrix_translate(&shader->paint_matrix, px_center_offset,
+ stfb->height - 1.0f + px_center_offset);
+ matrix_scale(&shader->paint_matrix, 1.0f, -1.0f);
+}
diff --git a/src/gallium/state_trackers/vega/shader.h b/src/gallium/state_trackers/vega/shader.h
index 847eee6a310..8b97e537efe 100644
--- a/src/gallium/state_trackers/vega/shader.h
+++ b/src/gallium/state_trackers/vega/shader.h
@@ -33,10 +33,13 @@ struct shader;
struct vg_paint;
struct vg_context;
struct vg_image;
+struct matrix;
struct shader *shader_create(struct vg_context *context);
void shader_destroy(struct shader *shader);
+void shader_set_color_transform(struct shader *shader, VGboolean set);
+
void shader_set_masking(struct shader *shader, VGboolean set);
VGboolean shader_is_masking(struct shader *shader);
@@ -51,6 +54,10 @@ VGboolean shader_drawing_image(struct shader *shader);
void shader_set_image(struct shader *shader, struct vg_image *img);
+void shader_set_surface_matrix(struct shader *shader,
+ const struct matrix *mat);
+void shader_set_paint_matrix(struct shader *shader, const struct matrix *mat);
+
void shader_bind(struct shader *shader);
#endif
diff --git a/src/gallium/state_trackers/vega/shaders_cache.c b/src/gallium/state_trackers/vega/shaders_cache.c
index e002a7ed428..023996ce2d8 100644
--- a/src/gallium/state_trackers/vega/shaders_cache.c
+++ b/src/gallium/state_trackers/vega/shaders_cache.c
@@ -50,14 +50,16 @@
/* Essentially we construct an ubber-shader based on the state
* of the pipeline. The stages are:
- * 1) Fill (mandatory, solid color/gradient/pattern/image draw)
- * 2) Image composition (image mode multiply and stencil)
- * 3) Mask
- * 4) Extended blend (multiply/screen/darken/lighten)
- * 5) Premultiply/Unpremultiply
- * 6) Color transform (to black and white)
+ * 1) Paint generation (color/gradient/pattern)
+ * 2) Image composition (normal/multiply/stencil)
+ * 3) Color transform
+ * 4) Per-channel alpha generation
+ * 5) Extended blend (multiply/screen/darken/lighten)
+ * 6) Mask
+ * 7) Premultiply/Unpremultiply
+ * 8) Color transform (to black and white)
*/
-#define SHADER_STAGES 6
+#define SHADER_STAGES 8
struct cached_shader {
void *driver_shader;
@@ -86,13 +88,6 @@ static INLINE struct tgsi_token *tokens_from_assembly(const char *txt, int num_t
return tokens;
}
-#define ALL_FILLS (VEGA_SOLID_FILL_SHADER | \
- VEGA_LINEAR_GRADIENT_SHADER | \
- VEGA_RADIAL_GRADIENT_SHADER | \
- VEGA_PATTERN_SHADER | \
- VEGA_IMAGE_NORMAL_SHADER)
-
-
/*
static const char max_shader_preamble[] =
"FRAG\n"
@@ -257,98 +252,126 @@ create_shader(struct pipe_context *pipe,
int id,
struct pipe_shader_state *shader)
{
- int idx = 0;
+ int idx = 0, sh;
const struct shader_asm_info * shaders[SHADER_STAGES];
- /* the shader has to have a fill */
- debug_assert(id & ALL_FILLS);
-
/* first stage */
- if (id & VEGA_SOLID_FILL_SHADER) {
- debug_assert(idx == 0);
- shaders[idx] = &shaders_asm[0];
- debug_assert(shaders_asm[0].id == VEGA_SOLID_FILL_SHADER);
- ++idx;
- }
- if ((id & VEGA_LINEAR_GRADIENT_SHADER)) {
- debug_assert(idx == 0);
- shaders[idx] = &shaders_asm[1];
- debug_assert(shaders_asm[1].id == VEGA_LINEAR_GRADIENT_SHADER);
- ++idx;
- }
- if ((id & VEGA_RADIAL_GRADIENT_SHADER)) {
- debug_assert(idx == 0);
- shaders[idx] = &shaders_asm[2];
- debug_assert(shaders_asm[2].id == VEGA_RADIAL_GRADIENT_SHADER);
- ++idx;
- }
- if ((id & VEGA_PATTERN_SHADER)) {
- debug_assert(idx == 0);
- debug_assert(shaders_asm[3].id == VEGA_PATTERN_SHADER);
- shaders[idx] = &shaders_asm[3];
- ++idx;
- }
- if ((id & VEGA_IMAGE_NORMAL_SHADER)) {
- debug_assert(idx == 0);
- debug_assert(shaders_asm[4].id == VEGA_IMAGE_NORMAL_SHADER);
- shaders[idx] = &shaders_asm[4];
- ++idx;
+ sh = SHADERS_GET_PAINT_SHADER(id);
+ switch (sh << SHADERS_PAINT_SHIFT) {
+ case VEGA_SOLID_FILL_SHADER:
+ case VEGA_LINEAR_GRADIENT_SHADER:
+ case VEGA_RADIAL_GRADIENT_SHADER:
+ case VEGA_PATTERN_SHADER:
+ case VEGA_PAINT_DEGENERATE_SHADER:
+ shaders[idx] = &shaders_paint_asm[(sh >> SHADERS_PAINT_SHIFT) - 1];
+ assert(shaders[idx]->id == sh);
+ idx++;
+ break;
+ default:
+ break;
}
/* second stage */
- if ((id & VEGA_IMAGE_MULTIPLY_SHADER)) {
- debug_assert(shaders_asm[5].id == VEGA_IMAGE_MULTIPLY_SHADER);
- shaders[idx] = &shaders_asm[5];
- ++idx;
- } else if ((id & VEGA_IMAGE_STENCIL_SHADER)) {
- debug_assert(shaders_asm[6].id == VEGA_IMAGE_STENCIL_SHADER);
- shaders[idx] = &shaders_asm[6];
- ++idx;
+ sh = SHADERS_GET_IMAGE_SHADER(id);
+ switch (sh) {
+ case VEGA_IMAGE_NORMAL_SHADER:
+ case VEGA_IMAGE_MULTIPLY_SHADER:
+ case VEGA_IMAGE_STENCIL_SHADER:
+ shaders[idx] = &shaders_image_asm[(sh >> SHADERS_IMAGE_SHIFT) - 1];
+ assert(shaders[idx]->id == sh);
+ idx++;
+ break;
+ default:
+ break;
}
+ /* sanity check */
+ assert(idx == ((!sh || sh == VEGA_IMAGE_NORMAL_SHADER) ? 1 : 2));
+
/* third stage */
- if ((id & VEGA_MASK_SHADER)) {
- debug_assert(idx == 1);
- debug_assert(shaders_asm[7].id == VEGA_MASK_SHADER);
- shaders[idx] = &shaders_asm[7];
- ++idx;
+ sh = SHADERS_GET_COLOR_TRANSFORM_SHADER(id);
+ switch (sh) {
+ case VEGA_COLOR_TRANSFORM_SHADER:
+ shaders[idx] = &shaders_color_transform_asm[
+ (sh >> SHADERS_COLOR_TRANSFORM_SHIFT) - 1];
+ assert(shaders[idx]->id == sh);
+ idx++;
+ break;
+ default:
+ break;
}
/* fourth stage */
- if ((id & VEGA_BLEND_MULTIPLY_SHADER)) {
- debug_assert(shaders_asm[8].id == VEGA_BLEND_MULTIPLY_SHADER);
- shaders[idx] = &shaders_asm[8];
- ++idx;
- } else if ((id & VEGA_BLEND_SCREEN_SHADER)) {
- debug_assert(shaders_asm[9].id == VEGA_BLEND_SCREEN_SHADER);
- shaders[idx] = &shaders_asm[9];
- ++idx;
- } else if ((id & VEGA_BLEND_DARKEN_SHADER)) {
- debug_assert(shaders_asm[10].id == VEGA_BLEND_DARKEN_SHADER);
- shaders[idx] = &shaders_asm[10];
- ++idx;
- } else if ((id & VEGA_BLEND_LIGHTEN_SHADER)) {
- debug_assert(shaders_asm[11].id == VEGA_BLEND_LIGHTEN_SHADER);
- shaders[idx] = &shaders_asm[11];
- ++idx;
+ sh = SHADERS_GET_ALPHA_SHADER(id);
+ switch (sh) {
+ case VEGA_ALPHA_NORMAL_SHADER:
+ case VEGA_ALPHA_PER_CHANNEL_SHADER:
+ shaders[idx] = &shaders_alpha_asm[
+ (sh >> SHADERS_ALPHA_SHIFT) - 1];
+ assert(shaders[idx]->id == sh);
+ idx++;
+ break;
+ default:
+ break;
}
/* fifth stage */
- if ((id & VEGA_PREMULTIPLY_SHADER)) {
- debug_assert(shaders_asm[12].id == VEGA_PREMULTIPLY_SHADER);
- shaders[idx] = &shaders_asm[12];
- ++idx;
- } else if ((id & VEGA_UNPREMULTIPLY_SHADER)) {
- debug_assert(shaders_asm[13].id == VEGA_UNPREMULTIPLY_SHADER);
- shaders[idx] = &shaders_asm[13];
- ++idx;
+ sh = SHADERS_GET_BLEND_SHADER(id);
+ switch (sh) {
+ case VEGA_BLEND_SRC_SHADER:
+ case VEGA_BLEND_SRC_OVER_SHADER:
+ case VEGA_BLEND_DST_OVER_SHADER:
+ case VEGA_BLEND_SRC_IN_SHADER:
+ case VEGA_BLEND_DST_IN_SHADER:
+ case VEGA_BLEND_MULTIPLY_SHADER:
+ case VEGA_BLEND_SCREEN_SHADER:
+ case VEGA_BLEND_DARKEN_SHADER:
+ case VEGA_BLEND_LIGHTEN_SHADER:
+ case VEGA_BLEND_ADDITIVE_SHADER:
+ shaders[idx] = &shaders_blend_asm[(sh >> SHADERS_BLEND_SHIFT) - 1];
+ assert(shaders[idx]->id == sh);
+ idx++;
+ break;
+ default:
+ break;
}
/* sixth stage */
- if ((id & VEGA_BW_SHADER)) {
- debug_assert(shaders_asm[14].id == VEGA_BW_SHADER);
- shaders[idx] = &shaders_asm[14];
- ++idx;
+ sh = SHADERS_GET_MASK_SHADER(id);
+ switch (sh) {
+ case VEGA_MASK_SHADER:
+ shaders[idx] = &shaders_mask_asm[(sh >> SHADERS_MASK_SHIFT) - 1];
+ assert(shaders[idx]->id == sh);
+ idx++;
+ break;
+ default:
+ break;
+ }
+
+ /* seventh stage */
+ sh = SHADERS_GET_PREMULTIPLY_SHADER(id);
+ switch (sh) {
+ case VEGA_PREMULTIPLY_SHADER:
+ case VEGA_UNPREMULTIPLY_SHADER:
+ shaders[idx] = &shaders_premultiply_asm[
+ (sh >> SHADERS_PREMULTIPLY_SHIFT) - 1];
+ assert(shaders[idx]->id == sh);
+ idx++;
+ break;
+ default:
+ break;
+ }
+
+ /* eighth stage */
+ sh = SHADERS_GET_BW_SHADER(id);
+ switch (sh) {
+ case VEGA_BW_SHADER:
+ shaders[idx] = &shaders_bw_asm[(sh >> SHADERS_BW_SHIFT) - 1];
+ assert(shaders[idx]->id == sh);
+ idx++;
+ break;
+ default:
+ break;
}
return combine_shaders(shaders, idx, pipe, shader);
diff --git a/src/gallium/state_trackers/vega/shaders_cache.h b/src/gallium/state_trackers/vega/shaders_cache.h
index feca58b61a9..05014f25dcc 100644
--- a/src/gallium/state_trackers/vega/shaders_cache.h
+++ b/src/gallium/state_trackers/vega/shaders_cache.h
@@ -33,26 +33,69 @@ struct pipe_context;
struct tgsi_token;
struct shaders_cache;
+#define _SHADERS_PAINT_BITS 3
+#define _SHADERS_IMAGE_BITS 2
+#define _SHADERS_COLOR_TRANSFORM_BITS 1
+#define _SHADERS_ALPHA_BITS 2
+#define _SHADERS_BLEND_BITS 4
+#define _SHADERS_MASK_BITS 1
+#define _SHADERS_PREMULTIPLY_BITS 2
+#define _SHADERS_BW_BITS 1
+
+#define SHADERS_PAINT_SHIFT (0)
+#define SHADERS_IMAGE_SHIFT (SHADERS_PAINT_SHIFT + _SHADERS_PAINT_BITS)
+#define SHADERS_COLOR_TRANSFORM_SHIFT (SHADERS_IMAGE_SHIFT + _SHADERS_IMAGE_BITS)
+#define SHADERS_ALPHA_SHIFT (SHADERS_COLOR_TRANSFORM_SHIFT + _SHADERS_COLOR_TRANSFORM_BITS)
+#define SHADERS_BLEND_SHIFT (SHADERS_ALPHA_SHIFT + _SHADERS_ALPHA_BITS)
+#define SHADERS_MASK_SHIFT (SHADERS_BLEND_SHIFT + _SHADERS_BLEND_BITS)
+#define SHADERS_PREMULTIPLY_SHIFT (SHADERS_MASK_SHIFT + _SHADERS_MASK_BITS)
+#define SHADERS_BW_SHIFT (SHADERS_PREMULTIPLY_SHIFT + _SHADERS_PREMULTIPLY_BITS)
+
+#define _SHADERS_GET_STAGE(stage, id) \
+ ((id) & (((1 << _SHADERS_ ## stage ## _BITS) - 1) << SHADERS_ ## stage ## _SHIFT))
+
+#define SHADERS_GET_PAINT_SHADER(id) _SHADERS_GET_STAGE(PAINT, id)
+#define SHADERS_GET_IMAGE_SHADER(id) _SHADERS_GET_STAGE(IMAGE, id)
+#define SHADERS_GET_COLOR_TRANSFORM_SHADER(id) _SHADERS_GET_STAGE(COLOR_TRANSFORM, id)
+#define SHADERS_GET_ALPHA_SHADER(id) _SHADERS_GET_STAGE(ALPHA, id)
+#define SHADERS_GET_BLEND_SHADER(id) _SHADERS_GET_STAGE(BLEND, id)
+#define SHADERS_GET_MASK_SHADER(id) _SHADERS_GET_STAGE(MASK, id)
+#define SHADERS_GET_PREMULTIPLY_SHADER(id) _SHADERS_GET_STAGE(PREMULTIPLY, id)
+#define SHADERS_GET_BW_SHADER(id) _SHADERS_GET_STAGE(BW, id)
+
enum VegaShaderType {
- VEGA_SOLID_FILL_SHADER = 1 << 0,
- VEGA_LINEAR_GRADIENT_SHADER = 1 << 1,
- VEGA_RADIAL_GRADIENT_SHADER = 1 << 2,
- VEGA_PATTERN_SHADER = 1 << 3,
- VEGA_IMAGE_NORMAL_SHADER = 1 << 4,
- VEGA_IMAGE_MULTIPLY_SHADER = 1 << 5,
- VEGA_IMAGE_STENCIL_SHADER = 1 << 6,
+ VEGA_SOLID_FILL_SHADER = 1 << SHADERS_PAINT_SHIFT,
+ VEGA_LINEAR_GRADIENT_SHADER = 2 << SHADERS_PAINT_SHIFT,
+ VEGA_RADIAL_GRADIENT_SHADER = 3 << SHADERS_PAINT_SHIFT,
+ VEGA_PATTERN_SHADER = 4 << SHADERS_PAINT_SHIFT,
+ VEGA_PAINT_DEGENERATE_SHADER = 5 << SHADERS_PAINT_SHIFT,
+
+ VEGA_IMAGE_NORMAL_SHADER = 1 << SHADERS_IMAGE_SHIFT,
+ VEGA_IMAGE_MULTIPLY_SHADER = 2 << SHADERS_IMAGE_SHIFT,
+ VEGA_IMAGE_STENCIL_SHADER = 3 << SHADERS_IMAGE_SHIFT,
+
+ VEGA_COLOR_TRANSFORM_SHADER = 1 << SHADERS_COLOR_TRANSFORM_SHIFT,
+
+ VEGA_ALPHA_NORMAL_SHADER = 1 << SHADERS_ALPHA_SHIFT,
+ VEGA_ALPHA_PER_CHANNEL_SHADER = 2 << SHADERS_ALPHA_SHIFT,
- VEGA_MASK_SHADER = 1 << 7,
+ VEGA_BLEND_SRC_SHADER = 1 << SHADERS_BLEND_SHIFT,
+ VEGA_BLEND_SRC_OVER_SHADER = 2 << SHADERS_BLEND_SHIFT,
+ VEGA_BLEND_DST_OVER_SHADER = 3 << SHADERS_BLEND_SHIFT,
+ VEGA_BLEND_SRC_IN_SHADER = 4 << SHADERS_BLEND_SHIFT,
+ VEGA_BLEND_DST_IN_SHADER = 5 << SHADERS_BLEND_SHIFT,
+ VEGA_BLEND_MULTIPLY_SHADER = 6 << SHADERS_BLEND_SHIFT,
+ VEGA_BLEND_SCREEN_SHADER = 7 << SHADERS_BLEND_SHIFT,
+ VEGA_BLEND_DARKEN_SHADER = 8 << SHADERS_BLEND_SHIFT,
+ VEGA_BLEND_LIGHTEN_SHADER = 9 << SHADERS_BLEND_SHIFT,
+ VEGA_BLEND_ADDITIVE_SHADER = 10<< SHADERS_BLEND_SHIFT,
- VEGA_BLEND_MULTIPLY_SHADER = 1 << 8,
- VEGA_BLEND_SCREEN_SHADER = 1 << 9,
- VEGA_BLEND_DARKEN_SHADER = 1 << 10,
- VEGA_BLEND_LIGHTEN_SHADER = 1 << 11,
+ VEGA_MASK_SHADER = 1 << SHADERS_MASK_SHIFT,
- VEGA_PREMULTIPLY_SHADER = 1 << 12,
- VEGA_UNPREMULTIPLY_SHADER = 1 << 13,
+ VEGA_PREMULTIPLY_SHADER = 1 << SHADERS_PREMULTIPLY_SHIFT,
+ VEGA_UNPREMULTIPLY_SHADER = 2 << SHADERS_PREMULTIPLY_SHIFT,
- VEGA_BW_SHADER = 1 << 14
+ VEGA_BW_SHADER = 1 << SHADERS_BW_SHIFT
};
struct vg_shader {
diff --git a/src/gallium/state_trackers/vega/st_inlines.h b/src/gallium/state_trackers/vega/st_inlines.h
deleted file mode 100644
index 7eaa67c76ae..00000000000
--- a/src/gallium/state_trackers/vega/st_inlines.h
+++ /dev/null
@@ -1,122 +0,0 @@
-/**************************************************************************
- *
- * Copyright 2009 VMware, Inc.
- * All Rights Reserved.
- *
- * Permission is hereby granted, free of charge, to any person obtaining a
- * copy of this software and associated documentation files (the
- * "Software"), to deal in the Software without restriction, including
- * without limitation the rights to use, copy, modify, merge, publish,
- * distribute, sub license, and/or sell copies of the Software, and to
- * permit persons to whom the Software is furnished to do so, subject to
- * the following conditions:
- *
- * The above copyright notice and this permission notice (including the
- * next paragraph) shall be included in all copies or substantial portions
- * of the Software.
- *
- * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
- * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
- * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
- * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
- * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
- * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
- * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
- *
- **************************************************************************/
-
-/**
- * Functions for checking if buffers/textures are referenced when we need
- * to read/write from/to them. Flush when needed.
- */
-
-#ifndef ST_INLINES_H
-#define ST_INLINES_H
-
-#include "vg_context.h"
-
-#include "pipe/p_context.h"
-#include "pipe/p_screen.h"
-#include "pipe/p_defines.h"
-#include "util/u_inlines.h"
-#include "pipe/p_state.h"
-
-static INLINE struct pipe_transfer *
-st_cond_flush_get_transfer(struct vg_context *st,
- struct pipe_resource *pt,
- unsigned int face,
- unsigned int level,
- unsigned int zslice,
- enum pipe_transfer_usage usage,
- unsigned int x, unsigned int y,
- unsigned int w, unsigned int h)
-{
- struct pipe_context *pipe = st->pipe;
-
- return pipe_get_transfer(pipe, pt, face, level, zslice, usage,
- x, y, w, h);
-}
-
-static INLINE struct pipe_transfer *
-st_no_flush_get_transfer(struct vg_context *st,
- struct pipe_resource *pt,
- unsigned int face,
- unsigned int level,
- unsigned int zslice,
- enum pipe_transfer_usage usage,
- unsigned int x, unsigned int y,
- unsigned int w, unsigned int h)
-{
- struct pipe_context *pipe = st->pipe;
-
- return pipe_get_transfer(pipe, pt, face, level,
- zslice, usage, x, y, w, h);
-}
-
-
-static INLINE void
-st_cond_flush_pipe_buffer_write(struct vg_context *st,
- struct pipe_resource *buf,
- unsigned int offset,
- unsigned int size,
- const void * data)
-{
- struct pipe_context *pipe = st->pipe;
-
- pipe_buffer_write(pipe, buf, offset, size, data);
-}
-
-static INLINE void
-st_no_flush_pipe_buffer_write(struct vg_context *st,
- struct pipe_resource *buf,
- unsigned int offset,
- unsigned int size,
- const void * data)
-{
- pipe_buffer_write(st->pipe, buf, offset, size, data);
-}
-
-static INLINE void
-st_cond_flush_pipe_buffer_read(struct vg_context *st,
- struct pipe_resource *buf,
- unsigned int offset,
- unsigned int size,
- void * data)
-{
- struct pipe_context *pipe = st->pipe;
-
- pipe_buffer_read(pipe, buf, offset, size, data);
-}
-
-static INLINE void
-st_no_flush_pipe_buffer_read(struct vg_context *st,
- struct pipe_resource *buf,
- unsigned int offset,
- unsigned int size,
- void * data)
-{
- pipe_buffer_read(st->pipe, buf, offset, size, data);
-}
-
-#endif
-
diff --git a/src/gallium/state_trackers/vega/text.c b/src/gallium/state_trackers/vega/text.c
new file mode 100644
index 00000000000..01ff602f58a
--- /dev/null
+++ b/src/gallium/state_trackers/vega/text.c
@@ -0,0 +1,250 @@
+/**************************************************************************
+ *
+ * Copyright 2010 LunarG, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#include "util/u_memory.h"
+#include "cso_cache/cso_hash.h"
+
+#include "text.h"
+#include "image.h"
+#include "path.h"
+#include "api.h"
+
+#ifdef OPENVG_VERSION_1_1
+
+struct vg_font {
+ struct vg_object base;
+ struct cso_hash *glyphs;
+};
+
+struct vg_glyph {
+ struct vg_object *object; /* it could be NULL */
+ VGboolean is_hinted;
+ VGfloat glyph_origin[2];
+ VGfloat escapement[2];
+};
+
+static VGboolean del_glyph(struct vg_font *font,
+ VGuint glyphIndex)
+{
+ struct vg_glyph *glyph;
+
+ glyph = (struct vg_glyph *)
+ cso_hash_take(font->glyphs, (unsigned) glyphIndex);
+ if (glyph)
+ FREE(glyph);
+
+ return (glyph != NULL);
+}
+
+static void add_glyph(struct vg_font *font,
+ VGuint glyphIndex,
+ struct vg_object *obj,
+ VGboolean isHinted,
+ const VGfloat glyphOrigin[2],
+ const VGfloat escapement[2])
+{
+ struct vg_glyph *glyph;
+
+ /* remove the existing one */
+ del_glyph(font, glyphIndex);
+
+ glyph = CALLOC_STRUCT(vg_glyph);
+ glyph->object = obj;
+ glyph->is_hinted = isHinted;
+ memcpy(glyph->glyph_origin, glyphOrigin, sizeof(glyphOrigin));
+ memcpy(glyph->escapement, escapement, sizeof(escapement));
+
+ cso_hash_insert(font->glyphs, (unsigned) glyphIndex, glyph);
+}
+
+static struct vg_glyph *get_glyph(struct vg_font *font,
+ VGuint glyphIndex)
+{
+ struct cso_hash_iter iter;
+
+ iter = cso_hash_find(font->glyphs, (unsigned) glyphIndex);
+ return (struct vg_glyph *) cso_hash_iter_data(iter);
+}
+
+static void vg_render_glyph(struct vg_context *ctx,
+ struct vg_glyph *glyph,
+ VGbitfield paintModes,
+ VGboolean allowAutoHinting)
+{
+ if (glyph->object && paintModes) {
+ struct vg_state *state = &ctx->state.vg;
+ struct matrix m;
+
+ m = state->glyph_user_to_surface_matrix;
+ matrix_translate(&m,
+ state->glyph_origin[0].f - glyph->glyph_origin[0],
+ state->glyph_origin[1].f - glyph->glyph_origin[1]);
+
+ if (glyph->object->type == VG_OBJECT_PATH) {
+ path_render((struct path *) glyph->object, paintModes, &m);
+ }
+ else {
+ assert(glyph->object->type == VG_OBJECT_IMAGE);
+ image_draw((struct vg_image *) glyph->object, &m);
+ }
+ }
+}
+
+static void vg_advance_glyph(struct vg_context *ctx,
+ struct vg_glyph *glyph,
+ VGfloat adjustment_x,
+ VGfloat adjustment_y,
+ VGboolean last)
+{
+ struct vg_value *glyph_origin = ctx->state.vg.glyph_origin;
+
+ glyph_origin[0].f += glyph->escapement[0] + adjustment_x;
+ glyph_origin[1].f += glyph->escapement[1] + adjustment_y;
+
+ if (last) {
+ glyph_origin[0].i = float_to_int_floor(glyph_origin[0].f);
+ glyph_origin[1].i = float_to_int_floor(glyph_origin[1].f);
+ }
+}
+
+struct vg_font *font_create(VGint glyphCapacityHint)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_font *font;
+
+ font = CALLOC_STRUCT(vg_font);
+ vg_init_object(&font->base, ctx, VG_OBJECT_FONT);
+ font->glyphs = cso_hash_create();
+
+ vg_context_add_object(ctx, VG_OBJECT_FONT, font);
+
+ return font;
+}
+
+void font_destroy(struct vg_font *font)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct cso_hash_iter iter;
+
+ vg_context_remove_object(ctx, VG_OBJECT_FONT, font);
+
+ iter = cso_hash_first_node(font->glyphs);
+ while (!cso_hash_iter_is_null(iter)) {
+ struct vg_glyph *glyph = (struct vg_glyph *) cso_hash_iter_data(iter);
+ FREE(glyph);
+ iter = cso_hash_iter_next(iter);
+ }
+ cso_hash_delete(font->glyphs);
+
+ FREE(font);
+}
+
+void font_set_glyph_to_path(struct vg_font *font,
+ VGuint glyphIndex,
+ struct path *path,
+ VGboolean isHinted,
+ const VGfloat glyphOrigin[2],
+ const VGfloat escapement[2])
+{
+ add_glyph(font, glyphIndex, (struct vg_object *) path,
+ isHinted, glyphOrigin, escapement);
+}
+
+void font_set_glyph_to_image(struct vg_font *font,
+ VGuint glyphIndex,
+ struct vg_image *image,
+ const VGfloat glyphOrigin[2],
+ const VGfloat escapement[2])
+{
+ add_glyph(font, glyphIndex, (struct vg_object *) image,
+ VG_TRUE, glyphOrigin, escapement);
+}
+
+void font_clear_glyph(struct vg_font *font,
+ VGuint glyphIndex)
+{
+ if (!del_glyph(font, glyphIndex)) {
+ struct vg_context *ctx = vg_current_context();
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ }
+}
+
+void font_draw_glyph(struct vg_font *font,
+ VGuint glyphIndex,
+ VGbitfield paintModes,
+ VGboolean allowAutoHinting)
+{
+ struct vg_context *ctx = vg_current_context();
+ struct vg_glyph *glyph;
+
+ glyph = get_glyph(font, glyphIndex);
+ if (!glyph) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+
+ vg_render_glyph(ctx, glyph, paintModes, allowAutoHinting);
+ vg_advance_glyph(ctx, glyph, 0.0f, 0.0f, VG_TRUE);
+}
+
+void font_draw_glyphs(struct vg_font *font,
+ VGint glyphCount,
+ const VGuint *glyphIndices,
+ const VGfloat *adjustments_x,
+ const VGfloat *adjustments_y,
+ VGbitfield paintModes,
+ VGboolean allowAutoHinting)
+{
+ struct vg_context *ctx = vg_current_context();
+ VGint i;
+
+ for (i = 0; i < glyphCount; ++i) {
+ if (!get_glyph(font, glyphIndices[i])) {
+ vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
+ return;
+ }
+ }
+
+ for (i = 0; i < glyphCount; ++i) {
+ struct vg_glyph *glyph;
+ VGfloat adj_x, adj_y;
+
+ glyph = get_glyph(font, glyphIndices[i]);
+
+ vg_render_glyph(ctx, glyph, paintModes, allowAutoHinting);
+
+ adj_x = (adjustments_x) ? adjustments_x[i] : 0.0f;
+ adj_y = (adjustments_y) ? adjustments_y[i] : 0.0f;
+ vg_advance_glyph(ctx, glyph, adj_x, adj_y, (i == glyphCount - 1));
+ }
+}
+
+VGint font_num_glyphs(struct vg_font *font)
+{
+ return cso_hash_size(font->glyphs);
+}
+
+#endif /* OPENVG_VERSION_1_1 */
diff --git a/src/gallium/state_trackers/vega/text.h b/src/gallium/state_trackers/vega/text.h
new file mode 100644
index 00000000000..6b3fa7323e9
--- /dev/null
+++ b/src/gallium/state_trackers/vega/text.h
@@ -0,0 +1,71 @@
+/**************************************************************************
+ *
+ * Copyright 2010 LunarG, Inc. All Rights Reserved.
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a
+ * copy of this software and associated documentation files (the
+ * "Software"), to deal in the Software without restriction, including
+ * without limitation the rights to use, copy, modify, merge, publish,
+ * distribute, sub license, and/or sell copies of the Software, and to
+ * permit persons to whom the Software is furnished to do so, subject to
+ * the following conditions:
+ *
+ * The above copyright notice and this permission notice (including the
+ * next paragraph) shall be included in all copies or substantial portions
+ * of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
+ * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT.
+ * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR
+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
+ * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
+ * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
+ *
+ **************************************************************************/
+
+#ifndef _TEXT_H
+#define _TEXT_H
+
+#include "vg_context.h"
+#include "cso_cache/cso_hash.h"
+
+struct vg_font;
+struct vg_image;
+struct path;
+
+struct vg_font *font_create(VGint glyphCapacityHint);
+void font_destroy(struct vg_font *font);
+
+void font_set_glyph_to_path(struct vg_font *font,
+ VGuint glyphIndex,
+ struct path *path,
+ VGboolean isHinted,
+ const VGfloat glyphOrigin[2],
+ const VGfloat escapement[2]);
+
+void font_set_glyph_to_image(struct vg_font *font,
+ VGuint glyphIndex,
+ struct vg_image *image,
+ const VGfloat glyphOrigin[2],
+ const VGfloat escapement[2]);
+
+void font_clear_glyph(struct vg_font *font,
+ VGuint glyphIndex);
+
+void font_draw_glyph(struct vg_font *font,
+ VGuint glyphIndex,
+ VGbitfield paintModes,
+ VGboolean allowAutoHinting);
+
+void font_draw_glyphs(struct vg_font *font,
+ VGint glyphCount,
+ const VGuint *glyphIndices,
+ const VGfloat *adjustments_x,
+ const VGfloat *adjustments_y,
+ VGbitfield paintModes,
+ VGboolean allowAutoHinting);
+
+VGint font_num_glyphs(struct vg_font *font);
+
+#endif /* _TEXT_H */
diff --git a/src/gallium/state_trackers/vega/vg_context.c b/src/gallium/state_trackers/vega/vg_context.c
index b1f98fa477d..0844012cc3b 100644
--- a/src/gallium/state_trackers/vega/vg_context.c
+++ b/src/gallium/state_trackers/vega/vg_context.c
@@ -31,9 +31,9 @@
#include "shaders_cache.h"
#include "shader.h"
#include "asm_util.h"
-#include "st_inlines.h"
#include "vg_manager.h"
#include "api.h"
+#include "mask.h"
#include "pipe/p_context.h"
#include "util/u_inlines.h"
@@ -44,6 +44,8 @@
#include "util/u_memory.h"
#include "util/u_blit.h"
#include "util/u_sampler.h"
+#include "util/u_surface.h"
+#include "util/u_format.h"
struct vg_context *_vg_context = 0;
@@ -52,19 +54,6 @@ struct vg_context * vg_current_context(void)
return _vg_context;
}
-static void init_clear(struct vg_context *st)
-{
- struct pipe_context *pipe = st->pipe;
-
- /* rasterizer state: bypass clipping */
- memset(&st->clear.raster, 0, sizeof(st->clear.raster));
- st->clear.raster.gl_rasterization_rules = 1;
-
- /* fragment shader state: color pass-through program */
- st->clear.fs =
- util_make_fragment_passthrough_shader(pipe);
-}
-
/**
* A depth/stencil rb will be needed regardless of what the visual says.
*/
@@ -101,7 +90,6 @@ struct vg_context * vg_create_context(struct pipe_context *pipe,
struct vg_context *share)
{
struct vg_context *ctx;
- unsigned i;
ctx = CALLOC_STRUCT(vg_context);
@@ -118,8 +106,6 @@ struct vg_context * vg_create_context(struct pipe_context *pipe,
ctx->cso_context = cso_create_context(pipe);
- init_clear(ctx);
-
ctx->default_paint = paint_create(ctx);
ctx->state.vg.stroke_paint = ctx->default_paint;
ctx->state.vg.fill_paint = ctx->default_paint;
@@ -127,6 +113,7 @@ struct vg_context * vg_create_context(struct pipe_context *pipe,
ctx->mask.sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->mask.sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->mask.sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->mask.sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
ctx->mask.sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
ctx->mask.sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
@@ -134,18 +121,12 @@ struct vg_context * vg_create_context(struct pipe_context *pipe,
ctx->blend_sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->blend_sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
+ ctx->blend_sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
ctx->blend_sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE;
ctx->blend_sampler.min_img_filter = PIPE_TEX_FILTER_NEAREST;
ctx->blend_sampler.mag_img_filter = PIPE_TEX_FILTER_NEAREST;
ctx->blend_sampler.normalized_coords = 0;
- for (i = 0; i < 2; i++) {
- ctx->velems[i].src_offset = i * 4 * sizeof(float);
- ctx->velems[i].instance_divisor = 0;
- ctx->velems[i].vertex_buffer_index = 0;
- ctx->velems[i].src_format = PIPE_FORMAT_R32G32B32A32_FLOAT;
- }
-
vg_set_error(ctx, VG_NO_ERROR);
ctx->owned_objects[VG_OBJECT_PAINT] = cso_hash_create();
@@ -166,7 +147,6 @@ struct vg_context * vg_create_context(struct pipe_context *pipe,
void vg_destroy_context(struct vg_context *ctx)
{
struct pipe_resource **cbuf = &ctx->mask.cbuf;
- struct pipe_resource **vsbuf = &ctx->vs_const_buffer;
util_destroy_blit(ctx->blit);
renderer_destroy(ctx->renderer);
@@ -177,29 +157,6 @@ void vg_destroy_context(struct vg_context *ctx)
if (*cbuf)
pipe_resource_reference(cbuf, NULL);
- if (*vsbuf)
- pipe_resource_reference(vsbuf, NULL);
-
- if (ctx->clear.fs) {
- cso_delete_fragment_shader(ctx->cso_context, ctx->clear.fs);
- ctx->clear.fs = NULL;
- }
-
- if (ctx->plain_vs) {
- vg_shader_destroy(ctx, ctx->plain_vs);
- ctx->plain_vs = NULL;
- }
- if (ctx->clear_vs) {
- vg_shader_destroy(ctx, ctx->clear_vs);
- ctx->clear_vs = NULL;
- }
- if (ctx->texture_vs) {
- vg_shader_destroy(ctx, ctx->texture_vs);
- ctx->texture_vs = NULL;
- }
-
- if (ctx->pass_through_depth_fs)
- vg_shader_destroy(ctx, ctx->pass_through_depth_fs);
if (ctx->mask.union_fs)
vg_shader_destroy(ctx, ctx->mask.union_fs);
if (ctx->mask.intersect_fs)
@@ -266,186 +223,195 @@ void vg_context_remove_object(struct vg_context *ctx,
}
}
-static void update_clip_state(struct vg_context *ctx)
+static struct pipe_resource *
+create_texture(struct pipe_context *pipe, enum pipe_format format,
+ VGint width, VGint height)
{
- struct pipe_depth_stencil_alpha_state *dsa = &ctx->state.g3d.dsa;
- struct vg_state *state = &ctx->state.vg;
-
- memset(dsa, 0, sizeof(struct pipe_depth_stencil_alpha_state));
-
- if (state->scissoring) {
- struct pipe_blend_state *blend = &ctx->state.g3d.blend;
- struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
- int i;
-
- dsa->depth.writemask = 1;/*glDepthMask(TRUE);*/
- dsa->depth.func = PIPE_FUNC_ALWAYS;
- dsa->depth.enabled = 1;
-
- cso_save_blend(ctx->cso_context);
- cso_save_fragment_shader(ctx->cso_context);
- /* set a passthrough shader */
- if (!ctx->pass_through_depth_fs)
- ctx->pass_through_depth_fs = shader_create_from_text(ctx->pipe,
- pass_through_depth_asm,
- 40,
- PIPE_SHADER_FRAGMENT);
- cso_set_fragment_shader_handle(ctx->cso_context,
- ctx->pass_through_depth_fs->driver);
- cso_set_depth_stencil_alpha(ctx->cso_context, dsa);
-
- ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 1.0, 0);
-
- /* disable color writes */
- blend->rt[0].colormask = 0; /*disable colorwrites*/
- cso_set_blend(ctx->cso_context, blend);
-
- /* enable scissoring */
- for (i = 0; i < state->scissor_rects_num; ++i) {
- const float x = state->scissor_rects[i * 4 + 0].f;
- const float y = state->scissor_rects[i * 4 + 1].f;
- const float width = state->scissor_rects[i * 4 + 2].f;
- const float height = state->scissor_rects[i * 4 + 3].f;
- VGfloat minx, miny, maxx, maxy;
-
- minx = 0;
- miny = 0;
- maxx = fb->width;
- maxy = fb->height;
-
- if (x > minx)
- minx = x;
- if (y > miny)
- miny = y;
-
- if (x + width < maxx)
- maxx = x + width;
- if (y + height < maxy)
- maxy = y + height;
-
- /* check for null space */
- if (minx >= maxx || miny >= maxy)
- minx = miny = maxx = maxy = 0;
-
- /*glClear(GL_DEPTH_BUFFER_BIT);*/
- renderer_draw_quad(ctx->renderer, minx, miny, maxx, maxy, 0.0f);
- }
-
- cso_restore_blend(ctx->cso_context);
- cso_restore_fragment_shader(ctx->cso_context);
-
- dsa->depth.enabled = 1; /* glEnable(GL_DEPTH_TEST); */
- dsa->depth.writemask = 0;/*glDepthMask(FALSE);*/
- dsa->depth.func = PIPE_FUNC_GEQUAL;
+ struct pipe_resource templ;
+
+ memset(&templ, 0, sizeof(templ));
+
+ if (format != PIPE_FORMAT_NONE) {
+ templ.format = format;
+ }
+ else {
+ templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
+ }
+
+ templ.target = PIPE_TEXTURE_2D;
+ templ.width0 = width;
+ templ.height0 = height;
+ templ.depth0 = 1;
+ templ.array_size = 1;
+ templ.last_level = 0;
+
+ if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) {
+ templ.bind = PIPE_BIND_DEPTH_STENCIL;
+ } else {
+ templ.bind = (PIPE_BIND_DISPLAY_TARGET |
+ PIPE_BIND_RENDER_TARGET |
+ PIPE_BIND_SAMPLER_VIEW);
}
+
+ return pipe->screen->resource_create(pipe->screen, &templ);
}
-void vg_validate_state(struct vg_context *ctx)
+static struct pipe_sampler_view *
+create_tex_and_view(struct pipe_context *pipe, enum pipe_format format,
+ VGint width, VGint height)
{
- vg_manager_validate_framebuffer(ctx);
+ struct pipe_resource *texture;
+ struct pipe_sampler_view view_templ;
+ struct pipe_sampler_view *view;
- if ((ctx->state.dirty & BLEND_DIRTY)) {
- struct pipe_blend_state *blend = &ctx->state.g3d.blend;
- memset(blend, 0, sizeof(struct pipe_blend_state));
- blend->rt[0].blend_enable = 1;
- blend->rt[0].colormask = PIPE_MASK_RGBA;
-
- switch (ctx->state.vg.blend_mode) {
- case VG_BLEND_SRC:
- blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend->rt[0].blend_enable = 0;
- break;
- case VG_BLEND_SRC_OVER:
- blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
- blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
- blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_INV_SRC_ALPHA;
- break;
- case VG_BLEND_DST_OVER:
- blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
- blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_INV_DST_ALPHA;
- blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
- blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_DST_ALPHA;
- break;
- case VG_BLEND_SRC_IN:
- blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
- blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_DST_ALPHA;
- blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- break;
- case VG_BLEND_DST_IN:
- blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ZERO;
- blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ZERO;
- blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
- blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_SRC_ALPHA;
- break;
- case VG_BLEND_MULTIPLY:
- case VG_BLEND_SCREEN:
- case VG_BLEND_DARKEN:
- case VG_BLEND_LIGHTEN:
- blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ZERO;
- blend->rt[0].blend_enable = 0;
- break;
- case VG_BLEND_ADDITIVE:
- blend->rt[0].rgb_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].alpha_src_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].rgb_dst_factor = PIPE_BLENDFACTOR_ONE;
- blend->rt[0].alpha_dst_factor = PIPE_BLENDFACTOR_ONE;
- break;
- default:
- assert(!"not implemented blend mode");
- }
- cso_set_blend(ctx->cso_context, &ctx->state.g3d.blend);
- }
- if ((ctx->state.dirty & RASTERIZER_DIRTY)) {
- struct pipe_rasterizer_state *raster = &ctx->state.g3d.rasterizer;
- memset(raster, 0, sizeof(struct pipe_rasterizer_state));
- raster->gl_rasterization_rules = 1;
- cso_set_rasterizer(ctx->cso_context, &ctx->state.g3d.rasterizer);
- }
- if ((ctx->state.dirty & VIEWPORT_DIRTY)) {
- struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
- const VGint param_bytes = 8 * sizeof(VGfloat);
- VGfloat vs_consts[8] = {
- 2.f/fb->width, 2.f/fb->height, 1, 1,
- -1, -1, 0, 0
- };
- struct pipe_resource **cbuf = &ctx->vs_const_buffer;
+ texture = create_texture(pipe, format, width, height);
- vg_set_viewport(ctx, VEGA_Y0_BOTTOM);
+ if (!texture)
+ return NULL;
- pipe_resource_reference(cbuf, NULL);
- *cbuf = pipe_buffer_create(ctx->pipe->screen,
- PIPE_BIND_CONSTANT_BUFFER,
- param_bytes);
-
- if (*cbuf) {
- st_no_flush_pipe_buffer_write(ctx, *cbuf,
- 0, param_bytes, vs_consts);
- }
- ctx->pipe->set_constant_buffer(ctx->pipe, PIPE_SHADER_VERTEX, 0, *cbuf);
+ u_sampler_view_default_template(&view_templ, texture, texture->format);
+ view = pipe->create_sampler_view(pipe, texture, &view_templ);
+ /* want the texture to go away if the view is freed */
+ pipe_resource_reference(&texture, NULL);
+
+ return view;
+}
+
+static void
+vg_context_update_surface_mask_view(struct vg_context *ctx,
+ uint width, uint height)
+{
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+ struct pipe_sampler_view *old_sampler_view = stfb->surface_mask_view;
+ struct pipe_context *pipe = ctx->pipe;
+
+ if (old_sampler_view &&
+ old_sampler_view->texture->width0 == width &&
+ old_sampler_view->texture->height0 == height)
+ return;
+
+ /*
+ we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to
+ this texture and use it as a sampler, so while this wastes some
+ space it makes both of those a lot simpler
+ */
+ stfb->surface_mask_view = create_tex_and_view(pipe,
+ PIPE_FORMAT_B8G8R8A8_UNORM, width, height);
+
+ if (!stfb->surface_mask_view) {
+ if (old_sampler_view)
+ pipe_sampler_view_reference(&old_sampler_view, NULL);
+ return;
}
- if ((ctx->state.dirty & VS_DIRTY)) {
- cso_set_vertex_shader_handle(ctx->cso_context,
- vg_plain_vs(ctx));
+
+ /* XXX could this call be avoided? */
+ vg_validate_state(ctx);
+
+ /* alpha mask starts with 1.f alpha */
+ mask_fill(0, 0, width, height, 1.f);
+
+ /* if we had an old surface copy it over */
+ if (old_sampler_view) {
+ struct pipe_box src_box;
+ u_box_origin_2d(MIN2(old_sampler_view->texture->width0,
+ stfb->surface_mask_view->texture->width0),
+ MIN2(old_sampler_view->texture->height0,
+ stfb->surface_mask_view->texture->height0),
+ &src_box);
+
+ pipe->resource_copy_region(pipe,
+ stfb->surface_mask_view->texture,
+ 0, 0, 0, 0,
+ old_sampler_view->texture,
+ 0, &src_box);
}
- /* must be last because it renders to the depth buffer*/
- if ((ctx->state.dirty & DEPTH_STENCIL_DIRTY)) {
- update_clip_state(ctx);
- cso_set_depth_stencil_alpha(ctx->cso_context, &ctx->state.g3d.dsa);
+ /* Free the old texture
+ */
+ if (old_sampler_view)
+ pipe_sampler_view_reference(&old_sampler_view, NULL);
+}
+
+static void
+vg_context_update_blend_texture_view(struct vg_context *ctx,
+ uint width, uint height)
+{
+ struct pipe_context *pipe = ctx->pipe;
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+ struct pipe_sampler_view *old = stfb->blend_texture_view;
+
+ if (old &&
+ old->texture->width0 == width &&
+ old->texture->height0 == height)
+ return;
+
+ stfb->blend_texture_view = create_tex_and_view(pipe,
+ PIPE_FORMAT_B8G8R8A8_UNORM, width, height);
+
+ pipe_sampler_view_reference(&old, NULL);
+}
+
+static boolean
+vg_context_update_depth_stencil_rb(struct vg_context * ctx,
+ uint width, uint height)
+{
+ struct st_renderbuffer *dsrb = ctx->draw_buffer->dsrb;
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_surface surf_tmpl;
+
+ if ((dsrb->width == width && dsrb->height == height) && dsrb->texture)
+ return FALSE;
+
+ /* unreference existing ones */
+ pipe_surface_reference(&dsrb->surface, NULL);
+ pipe_resource_reference(&dsrb->texture, NULL);
+ dsrb->width = dsrb->height = 0;
+
+ dsrb->texture = create_texture(pipe, dsrb->format, width, height);
+ if (!dsrb->texture)
+ return TRUE;
+
+ memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+ u_surface_default_template(&surf_tmpl, dsrb->texture,
+ PIPE_BIND_DEPTH_STENCIL);
+ dsrb->surface = pipe->create_surface(pipe,
+ dsrb->texture,
+ &surf_tmpl);
+ if (!dsrb->surface) {
+ pipe_resource_reference(&dsrb->texture, NULL);
+ return TRUE;
}
+ dsrb->width = width;
+ dsrb->height = height;
+
+ assert(dsrb->surface->width == width);
+ assert(dsrb->surface->height == height);
+
+ return TRUE;
+}
+
+void vg_validate_state(struct vg_context *ctx)
+{
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+
+ vg_manager_validate_framebuffer(ctx);
+
+ if (vg_context_update_depth_stencil_rb(ctx, stfb->width, stfb->height))
+ ctx->state.dirty |= DEPTH_STENCIL_DIRTY;
+
+ /* blend state depends on fb format */
+ if (ctx->state.dirty & FRAMEBUFFER_DIRTY)
+ ctx->state.dirty |= BLEND_DIRTY;
+
+ renderer_validate(ctx->renderer, ctx->state.dirty,
+ ctx->draw_buffer, &ctx->state.vg);
+
+ ctx->state.dirty = 0;
+
shader_set_masking(ctx->shader, ctx->state.vg.masking);
shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
-
- ctx->state.dirty = NONE_DIRTY;
+ shader_set_color_transform(ctx->shader, ctx->state.vg.color_transform);
}
VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)
@@ -468,130 +434,94 @@ void vg_set_error(struct vg_context *ctx,
ctx->_error = code;
}
-void vg_prepare_blend_surface(struct vg_context *ctx)
+static void vg_prepare_blend_texture(struct vg_context *ctx,
+ struct pipe_sampler_view *src)
+{
+ struct st_framebuffer *stfb = ctx->draw_buffer;
+ struct pipe_surface *surf;
+ struct pipe_surface surf_tmpl;
+
+ vg_context_update_blend_texture_view(ctx, stfb->width, stfb->height);
+
+ memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+ u_surface_default_template(&surf_tmpl, stfb->blend_texture_view->texture,
+ PIPE_BIND_RENDER_TARGET);
+ surf = ctx->pipe->create_surface(ctx->pipe,
+ stfb->blend_texture_view->texture,
+ &surf_tmpl);
+ if (surf) {
+ util_blit_pixels_tex(ctx->blit,
+ src, 0, 0, stfb->width, stfb->height,
+ surf, 0, 0, stfb->width, stfb->height,
+ 0.0, PIPE_TEX_MIPFILTER_NEAREST);
+
+ pipe_surface_reference(&surf, NULL);
+ }
+}
+
+struct pipe_sampler_view *vg_prepare_blend_surface(struct vg_context *ctx)
{
- struct pipe_surface *dest_surface = NULL;
struct pipe_context *pipe = ctx->pipe;
struct pipe_sampler_view *view;
struct pipe_sampler_view view_templ;
struct st_framebuffer *stfb = ctx->draw_buffer;
struct st_renderbuffer *strb = stfb->strb;
- /* first finish all pending rendering */
- vgFinish();
+ vg_validate_state(ctx);
u_sampler_view_default_template(&view_templ, strb->texture, strb->texture->format);
view = pipe->create_sampler_view(pipe, strb->texture, &view_templ);
- dest_surface = pipe->screen->get_tex_surface(pipe->screen,
- stfb->blend_texture_view->texture,
- 0, 0, 0,
- PIPE_BIND_RENDER_TARGET);
- /* flip it, because we want to use it as a sampler */
- util_blit_pixels_tex(ctx->blit,
- view,
- 0, strb->height,
- strb->width, 0,
- dest_surface,
- 0, 0,
- strb->width, strb->height,
- 0.0, PIPE_TEX_MIPFILTER_NEAREST);
-
- if (dest_surface)
- pipe_surface_reference(&dest_surface, NULL);
-
- /* make sure it's complete */
- vgFinish();
+ vg_prepare_blend_texture(ctx, view);
pipe_sampler_view_reference(&view, NULL);
+
+ return stfb->blend_texture_view;
}
-void vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
+struct pipe_sampler_view *vg_prepare_blend_surface_from_mask(struct vg_context *ctx)
{
- struct pipe_surface *dest_surface = NULL;
- struct pipe_context *pipe = ctx->pipe;
struct st_framebuffer *stfb = ctx->draw_buffer;
- struct st_renderbuffer *strb = stfb->strb;
vg_validate_state(ctx);
- /* first finish all pending rendering */
- vgFinish();
-
- dest_surface = pipe->screen->get_tex_surface(pipe->screen,
- stfb->blend_texture_view->texture,
- 0, 0, 0,
- PIPE_BIND_RENDER_TARGET);
-
- /* flip it, because we want to use it as a sampler */
- util_blit_pixels_tex(ctx->blit,
- stfb->alpha_mask_view,
- 0, strb->height,
- strb->width, 0,
- dest_surface,
- 0, 0,
- strb->width, strb->height,
- 0.0, PIPE_TEX_MIPFILTER_NEAREST);
-
- /* make sure it's complete */
- vgFinish();
-
- if (dest_surface)
- pipe_surface_reference(&dest_surface, NULL);
+ vg_context_update_surface_mask_view(ctx, stfb->width, stfb->height);
+ vg_prepare_blend_texture(ctx, stfb->surface_mask_view);
+
+ return stfb->blend_texture_view;
}
-void * vg_plain_vs(struct vg_context *ctx)
+struct pipe_sampler_view *vg_get_surface_mask(struct vg_context *ctx)
{
- if (!ctx->plain_vs) {
- ctx->plain_vs = shader_create_from_text(ctx->pipe,
- vs_plain_asm,
- 200,
- PIPE_SHADER_VERTEX);
- }
+ struct st_framebuffer *stfb = ctx->draw_buffer;
- return ctx->plain_vs->driver;
-}
+ vg_context_update_surface_mask_view(ctx, stfb->width, stfb->height);
+ return stfb->surface_mask_view;
+}
-void * vg_clear_vs(struct vg_context *ctx)
+/**
+ * A transformation from window coordinates to paint coordinates.
+ */
+VGboolean vg_get_paint_matrix(struct vg_context *ctx,
+ const struct matrix *paint_to_user,
+ const struct matrix *user_to_surface,
+ struct matrix *mat)
{
- if (!ctx->clear_vs) {
- ctx->clear_vs = shader_create_from_text(ctx->pipe,
- vs_clear_asm,
- 200,
- PIPE_SHADER_VERTEX);
- }
+ struct matrix tmp;
- return ctx->clear_vs->driver;
-}
+ /* get user-to-paint matrix */
+ memcpy(mat, paint_to_user, sizeof(*paint_to_user));
+ if (!matrix_invert(mat))
+ return VG_FALSE;
-void * vg_texture_vs(struct vg_context *ctx)
-{
- if (!ctx->texture_vs) {
- ctx->texture_vs = shader_create_from_text(ctx->pipe,
- vs_texture_asm,
- 200,
- PIPE_SHADER_VERTEX);
- }
+ /* get surface-to-user matrix */
+ memcpy(&tmp, user_to_surface, sizeof(*user_to_surface));
+ if (!matrix_invert(&tmp))
+ return VG_FALSE;
- return ctx->texture_vs->driver;
-}
+ matrix_mult(mat, &tmp);
-void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation)
-{
- struct pipe_viewport_state viewport;
- struct pipe_framebuffer_state *fb = &ctx->state.g3d.fb;
- VGfloat y_scale = (orientation == VEGA_Y0_BOTTOM) ? -2.f : 2.f;
-
- viewport.scale[0] = fb->width / 2.f;
- viewport.scale[1] = fb->height / y_scale;
- viewport.scale[2] = 1.0;
- viewport.scale[3] = 1.0;
- viewport.translate[0] = fb->width / 2.f;
- viewport.translate[1] = fb->height / 2.f;
- viewport.translate[2] = 0.0;
- viewport.translate[3] = 0.0;
-
- cso_set_viewport(ctx->cso_context, &viewport);
+ return VG_TRUE;
}
diff --git a/src/gallium/state_trackers/vega/vg_context.h b/src/gallium/state_trackers/vega/vg_context.h
index 80a6c07c693..d616a20a3d9 100644
--- a/src/gallium/state_trackers/vega/vg_context.h
+++ b/src/gallium/state_trackers/vega/vg_context.h
@@ -56,7 +56,7 @@ struct st_framebuffer {
struct st_renderbuffer *strb;
struct st_renderbuffer *dsrb;
- struct pipe_sampler_view *alpha_mask_view;
+ struct pipe_sampler_view *surface_mask_view;
struct pipe_sampler_view *blend_texture_view;
@@ -78,14 +78,13 @@ enum vg_object_type {
VG_OBJECT_LAST
};
enum dirty_state {
- NONE_DIRTY = 0<<0,
- BLEND_DIRTY = 1<<1,
- RASTERIZER_DIRTY = 1<<2,
- VIEWPORT_DIRTY = 1<<3,
- VS_DIRTY = 1<<4,
- DEPTH_STENCIL_DIRTY = 1<<5,
- ALL_DIRTY = BLEND_DIRTY | RASTERIZER_DIRTY |
- VIEWPORT_DIRTY | VS_DIRTY | DEPTH_STENCIL_DIRTY
+ BLEND_DIRTY = 1 << 0,
+ FRAMEBUFFER_DIRTY = 1 << 1,
+ DEPTH_STENCIL_DIRTY = 1 << 2,
+
+ ALL_DIRTY = BLEND_DIRTY |
+ FRAMEBUFFER_DIRTY |
+ DEPTH_STENCIL_DIRTY
};
struct vg_context
@@ -98,13 +97,6 @@ struct vg_context
struct {
struct vg_state vg;
- struct {
- struct pipe_blend_state blend;
- struct pipe_rasterizer_state rasterizer;
- struct pipe_shader_state vs_state;
- struct pipe_depth_stencil_alpha_state dsa;
- struct pipe_framebuffer_state fb;
- } g3d;
VGbitfield dirty;
} state;
@@ -116,14 +108,6 @@ struct vg_context
struct cso_hash *owned_objects[VG_OBJECT_LAST];
struct {
- struct pipe_shader_state vert_shader;
- struct pipe_shader_state frag_shader;
- struct pipe_rasterizer_state raster;
- void *fs;
- float vertices[4][2][4]; /**< vertex pos + color */
- } clear;
-
- struct {
struct pipe_resource *cbuf;
struct pipe_sampler_state sampler;
@@ -133,31 +117,16 @@ struct vg_context
struct vg_shader *set_fs;
} mask;
- struct vg_shader *pass_through_depth_fs;
-
struct cso_context *cso_context;
- struct pipe_resource *stencil_quad;
- VGfloat stencil_vertices[4][2][4];
-
struct renderer *renderer;
struct shaders_cache *sc;
struct shader *shader;
struct pipe_sampler_state blend_sampler;
- struct {
- struct pipe_resource *buffer;
- void *color_matrix_fs;
- } filter;
struct vg_paint *default_paint;
struct blit_state *blit;
-
- struct vg_shader *plain_vs;
- struct vg_shader *clear_vs;
- struct vg_shader *texture_vs;
- struct pipe_resource *vs_const_buffer;
- struct pipe_vertex_element velems[2];
};
struct vg_object {
@@ -189,9 +158,15 @@ void vg_validate_state(struct vg_context *ctx);
void vg_set_error(struct vg_context *ctx,
VGErrorCode code);
-void vg_prepare_blend_surface(struct vg_context *ctx);
-void vg_prepare_blend_surface_from_mask(struct vg_context *ctx);
+struct pipe_sampler_view *vg_prepare_blend_surface(struct vg_context *ctx);
+struct pipe_sampler_view *vg_prepare_blend_surface_from_mask(struct vg_context *ctx);
+struct pipe_sampler_view *vg_get_surface_mask(struct vg_context *ctx);
+
+VGboolean vg_get_paint_matrix(struct vg_context *ctx,
+ const struct matrix *paint_to_user,
+ const struct matrix *user_to_surface,
+ struct matrix *mat);
static INLINE VGboolean is_aligned_to(const void *ptr, VGbyte alignment)
{
@@ -292,13 +267,4 @@ static INLINE void vg_bound_rect(VGfloat coords[4],
}
}
-void *vg_plain_vs(struct vg_context *ctx);
-void *vg_clear_vs(struct vg_context *ctx);
-void *vg_texture_vs(struct vg_context *ctx);
-typedef enum {
- VEGA_Y0_TOP,
- VEGA_Y0_BOTTOM
-} VegaOrientation;
-void vg_set_viewport(struct vg_context *ctx, VegaOrientation orientation);
-
#endif
diff --git a/src/gallium/state_trackers/vega/vg_manager.c b/src/gallium/state_trackers/vega/vg_manager.c
index 232deefa166..de935768b22 100644
--- a/src/gallium/state_trackers/vega/vg_manager.c
+++ b/src/gallium/state_trackers/vega/vg_manager.c
@@ -33,168 +33,22 @@
#include "pipe/p_screen.h"
#include "util/u_memory.h"
#include "util/u_inlines.h"
-#include "util/u_format.h"
#include "util/u_sampler.h"
+#include "util/u_box.h"
+#include "util/u_surface.h"
#include "vg_api.h"
#include "vg_manager.h"
#include "vg_context.h"
#include "image.h"
-#include "mask.h"
#include "api.h"
-static struct pipe_resource *
-create_texture(struct pipe_context *pipe, enum pipe_format format,
- VGint width, VGint height)
-{
- struct pipe_resource templ;
-
- memset(&templ, 0, sizeof(templ));
-
- if (format != PIPE_FORMAT_NONE) {
- templ.format = format;
- }
- else {
- templ.format = PIPE_FORMAT_B8G8R8A8_UNORM;
- }
-
- templ.target = PIPE_TEXTURE_2D;
- templ.width0 = width;
- templ.height0 = height;
- templ.depth0 = 1;
- templ.last_level = 0;
-
- if (util_format_get_component_bits(format, UTIL_FORMAT_COLORSPACE_ZS, 1)) {
- templ.bind = PIPE_BIND_DEPTH_STENCIL;
- } else {
- templ.bind = (PIPE_BIND_DISPLAY_TARGET |
- PIPE_BIND_RENDER_TARGET |
- PIPE_BIND_SAMPLER_VIEW);
- }
-
- return pipe->screen->resource_create(pipe->screen, &templ);
-}
-
-static struct pipe_sampler_view *
-create_tex_and_view(struct pipe_context *pipe, enum pipe_format format,
- VGint width, VGint height)
-{
- struct pipe_resource *texture;
- struct pipe_sampler_view view_templ;
- struct pipe_sampler_view *view;
-
- texture = create_texture(pipe, format, width, height);
-
- if (!texture)
- return NULL;
-
- u_sampler_view_default_template(&view_templ, texture, texture->format);
- view = pipe->create_sampler_view(pipe, texture, &view_templ);
- /* want the texture to go away if the view is freed */
- pipe_resource_reference(&texture, NULL);
-
- return view;
-}
-
-static void
-setup_new_alpha_mask(struct vg_context *ctx, struct st_framebuffer *stfb)
-{
- struct pipe_context *pipe = ctx->pipe;
- struct pipe_sampler_view *old_sampler_view = stfb->alpha_mask_view;
-
- /*
- we use PIPE_FORMAT_B8G8R8A8_UNORM because we want to render to
- this texture and use it as a sampler, so while this wastes some
- space it makes both of those a lot simpler
- */
- stfb->alpha_mask_view = create_tex_and_view(pipe,
- PIPE_FORMAT_B8G8R8A8_UNORM, stfb->width, stfb->height);
-
- if (!stfb->alpha_mask_view) {
- if (old_sampler_view)
- pipe_sampler_view_reference(&old_sampler_view, NULL);
- return;
- }
-
- /* XXX could this call be avoided? */
- vg_validate_state(ctx);
-
- /* alpha mask starts with 1.f alpha */
- mask_fill(0, 0, stfb->width, stfb->height, 1.f);
-
- /* if we had an old surface copy it over */
- if (old_sampler_view) {
- struct pipe_subresource subsurf, subold_surf;
- subsurf.face = 0;
- subsurf.level = 0;
- subold_surf.face = 0;
- subold_surf.level = 0;
- pipe->resource_copy_region(pipe,
- stfb->alpha_mask_view->texture,
- subsurf,
- 0, 0, 0,
- old_sampler_view->texture,
- subold_surf,
- 0, 0, 0,
- MIN2(old_sampler_view->texture->width0,
- stfb->alpha_mask_view->texture->width0),
- MIN2(old_sampler_view->texture->height0,
- stfb->alpha_mask_view->texture->height0));
- }
-
- /* Free the old texture
- */
- if (old_sampler_view)
- pipe_sampler_view_reference(&old_sampler_view, NULL);
-}
-
-static boolean
-vg_context_update_depth_stencil_rb(struct vg_context * ctx,
- uint width, uint height)
-{
- struct st_renderbuffer *dsrb = ctx->draw_buffer->dsrb;
- struct pipe_context *pipe = ctx->pipe;
- unsigned surface_usage;
-
- if ((dsrb->width == width && dsrb->height == height) && dsrb->texture)
- return FALSE;
-
- /* unreference existing ones */
- pipe_surface_reference(&dsrb->surface, NULL);
- pipe_resource_reference(&dsrb->texture, NULL);
- dsrb->width = dsrb->height = 0;
-
- /* Probably need dedicated flags for surface usage too:
- */
- surface_usage = PIPE_BIND_DEPTH_STENCIL; /* XXX: was: RENDER_TARGET */
-
- dsrb->texture = create_texture(pipe, dsrb->format, width, height);
- if (!dsrb->texture)
- return TRUE;
-
- dsrb->surface = pipe->screen->get_tex_surface(pipe->screen,
- dsrb->texture,
- 0, 0, 0,
- surface_usage);
- if (!dsrb->surface) {
- pipe_resource_reference(&dsrb->texture, NULL);
- return TRUE;
- }
-
- dsrb->width = width;
- dsrb->height = height;
-
- assert(dsrb->surface->width == width);
- assert(dsrb->surface->height == height);
-
- return TRUE;
-}
-
static boolean
vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt)
{
struct st_renderbuffer *strb = ctx->draw_buffer->strb;
- struct pipe_screen *screen = ctx->pipe->screen;
+ struct pipe_context *pipe = ctx->pipe;
+ struct pipe_surface surf_tmpl;
if (strb->texture == pt) {
pipe_resource_reference(&pt, NULL);
@@ -207,8 +61,12 @@ vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt)
strb->width = strb->height = 0;
strb->texture = pt;
- strb->surface = screen->get_tex_surface(screen, strb->texture, 0, 0, 0,
- PIPE_BIND_RENDER_TARGET);
+
+ memset(&surf_tmpl, 0, sizeof(surf_tmpl));
+ u_surface_default_template(&surf_tmpl, strb->texture,
+ PIPE_BIND_RENDER_TARGET);
+ strb->surface = pipe->create_surface(pipe, strb->texture, &surf_tmpl);
+
if (!strb->surface) {
pipe_resource_reference(&strb->texture, NULL);
return TRUE;
@@ -220,49 +78,6 @@ vg_context_update_color_rb(struct vg_context *ctx, struct pipe_resource *pt)
return TRUE;
}
-static void
-vg_context_update_draw_buffer(struct vg_context *ctx, struct pipe_resource *pt)
-{
- struct st_framebuffer *stfb = ctx->draw_buffer;
- boolean new_cbuf, new_zsbuf, new_size;
-
- new_cbuf = vg_context_update_color_rb(ctx, pt);
- new_zsbuf =
- vg_context_update_depth_stencil_rb(ctx, pt->width0, pt->height0);
-
- new_size = (stfb->width != pt->width0 || stfb->height != pt->height0);
- stfb->width = pt->width0;
- stfb->height = pt->height0;
-
- if (new_cbuf || new_zsbuf || new_size) {
- struct pipe_framebuffer_state *state = &ctx->state.g3d.fb;
-
- memset(state, 0, sizeof(struct pipe_framebuffer_state));
- state->width = stfb->width;
- state->height = stfb->height;
- state->nr_cbufs = 1;
- state->cbufs[0] = stfb->strb->surface;
- state->zsbuf = stfb->dsrb->surface;
-
- cso_set_framebuffer(ctx->cso_context, state);
- }
-
- if (new_zsbuf || new_size) {
- ctx->state.dirty |= VIEWPORT_DIRTY;
- ctx->state.dirty |= DEPTH_STENCIL_DIRTY;/*to reset the scissors*/
-
- ctx->pipe->clear(ctx->pipe, PIPE_CLEAR_DEPTHSTENCIL, NULL, 0.0, 0);
-
- /* we need all the other state already set */
-
- setup_new_alpha_mask(ctx, stfb);
-
- pipe_sampler_view_reference( &stfb->blend_texture_view, NULL);
- stfb->blend_texture_view = create_tex_and_view(ctx->pipe,
- PIPE_FORMAT_B8G8R8A8_UNORM, stfb->width, stfb->height);
- }
-}
-
/**
* Flush the front buffer if the current context renders to the front buffer.
*/
@@ -304,15 +119,16 @@ vg_manager_validate_framebuffer(struct vg_context *ctx)
if (!stfb->iface->validate(stfb->iface, &stfb->strb_att, 1, &pt) || !pt)
return;
- /*
- * unset draw_buffer_invalid first because vg_context_update_draw_buffer
- * will cause the framebuffer to be validated again because of a call to
- * vg_validate_state
- */
p_atomic_set(&ctx->draw_buffer_invalid, FALSE);
- vg_context_update_draw_buffer(ctx, pt);
-}
+ if (vg_context_update_color_rb(ctx, pt) ||
+ stfb->width != pt->width0 ||
+ stfb->height != pt->height0)
+ ctx->state.dirty |= FRAMEBUFFER_DIRTY;
+
+ stfb->width = pt->width0;
+ stfb->height = pt->height0;
+}
static void
vg_context_notify_invalid_framebuffer(struct st_context_iface *stctxi,
@@ -336,7 +152,10 @@ static void
vg_context_destroy(struct st_context_iface *stctxi)
{
struct vg_context *ctx = (struct vg_context *) stctxi;
+ struct pipe_context *pipe = ctx->pipe;
+
vg_destroy_context(ctx);
+ pipe->destroy(pipe);
}
static struct st_context_iface *
@@ -535,6 +354,7 @@ vg_api_destroy(struct st_api *stapi)
}
static const struct st_api vg_api = {
+ "Vega " VEGA_VERSION_STRING,
ST_API_OPENVG,
ST_PROFILE_DEFAULT_MASK,
vg_api_destroy,