gallium: remove pipe_surface::usage
[mesa.git] / src / gallium / state_trackers / vega / vg_context.c
index b9dbc4f00b0149384eb1d556e5d593ed50efb35c..c63618816835143e79ea9bc9d958edea200954ff 100644 (file)
 #include "renderer.h"
 #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 "handle.h"
 
 #include "pipe/p_context.h"
 #include "util/u_inlines.h"
 
 #include "cso_cache/cso_context.h"
 
-#include "util/u_simple_shaders.h"
 #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 +53,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.
  */
@@ -73,15 +61,15 @@ choose_depth_stencil_format(struct vg_context *ctx)
 {
    struct pipe_screen *screen = ctx->pipe->screen;
    enum pipe_format formats[] = {
-      PIPE_FORMAT_Z24_UNORM_S8_USCALED,
-      PIPE_FORMAT_S8_USCALED_Z24_UNORM,
+      PIPE_FORMAT_Z24_UNORM_S8_UINT,
+      PIPE_FORMAT_S8_UINT_Z24_UNORM,
       PIPE_FORMAT_NONE
    };
    enum pipe_format *fmt;
 
    for (fmt = formats; *fmt != PIPE_FORMAT_NONE; fmt++) {
       if (screen->is_format_supported(screen, *fmt,
-               PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL, 0))
+               PIPE_TEXTURE_2D, 0, PIPE_BIND_DEPTH_STENCIL))
          break;
    }
 
@@ -101,7 +89,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 +105,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;
@@ -141,13 +126,6 @@ struct vg_context * vg_create_context(struct pipe_context *pipe,
    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();
@@ -168,7 +146,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);
@@ -179,29 +156,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)
@@ -229,62 +183,246 @@ void vg_init_object(struct vg_object *obj, struct vg_context *ctx, enum vg_objec
 {
    obj->type = type;
    obj->ctx = ctx;
+   obj->handle = create_handle(obj);
+}
+
+/** free object resources, but not the object itself */
+void vg_free_object(struct vg_object *obj)
+{
+   obj->type = 0;
+   obj->ctx = NULL;
+   destroy_handle(obj->handle);
 }
 
 VGboolean vg_context_is_object_valid(struct vg_context *ctx,
                                 enum vg_object_type type,
-                                void *ptr)
+                                VGHandle handle)
 {
     if (ctx) {
        struct cso_hash *hash = ctx->owned_objects[type];
        if (!hash)
           return VG_FALSE;
-       return cso_hash_contains(hash, (unsigned)(long)ptr);
+       return cso_hash_contains(hash, (unsigned) handle);
     }
     return VG_FALSE;
 }
 
 void vg_context_add_object(struct vg_context *ctx,
-                           enum vg_object_type type,
-                           void *ptr)
+                           struct vg_object *obj)
 {
     if (ctx) {
-       struct cso_hash *hash = ctx->owned_objects[type];
+       struct cso_hash *hash = ctx->owned_objects[obj->type];
        if (!hash)
           return;
-       cso_hash_insert(hash, (unsigned)(long)ptr, ptr);
+       cso_hash_insert(hash, (unsigned) obj->handle, obj);
     }
 }
 
 void vg_context_remove_object(struct vg_context *ctx,
-                              enum vg_object_type type,
-                              void *ptr)
+                              struct vg_object *obj)
 {
    if (ctx) {
-      struct cso_hash *hash = ctx->owned_objects[type];
+      struct cso_hash *hash = ctx->owned_objects[obj->type];
       if (!hash)
          return;
-      cso_hash_take(hash, (unsigned)(long)ptr);
+      cso_hash_take(hash, (unsigned) obj->handle);
+   }
+}
+
+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.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);
+}
+
+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
+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;
+   }
+
+   /* 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);
+   }
+
+   /* 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;
+
+   u_surface_default_template(&surf_tmpl, dsrb->texture);
+   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 and paint color */
+   if ((ctx->state.dirty & FRAMEBUFFER_DIRTY) ||
+       (ctx->state.dirty & PAINT_DIRTY))
+      ctx->state.dirty |= BLEND_DIRTY;
+
    renderer_validate(ctx->renderer, ctx->state.dirty,
          ctx->draw_buffer, &ctx->state.vg);
 
-   ctx->state.dirty = NONE_DIRTY;
+   ctx->state.dirty = 0;
 
    shader_set_masking(ctx->shader, ctx->state.vg.masking);
    shader_set_image_mode(ctx->shader, ctx->state.vg.image_mode);
+   shader_set_color_transform(ctx->shader, ctx->state.vg.color_transform);
 }
 
-VGboolean vg_object_is_valid(void *ptr, enum vg_object_type type)
+VGboolean vg_object_is_valid(VGHandle object, enum vg_object_type type)
 {
-   struct vg_object *obj = ptr;
-   if (ptr && is_aligned(obj) && obj->type == type)
+   struct vg_object *obj = handle_to_object(object);
+   if (obj && is_aligned(obj) && obj->type == type)
       return VG_TRUE;
    else
       return VG_FALSE;
@@ -301,111 +439,92 @@ 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);
+
+   u_surface_default_template(&surf_tmpl, stfb->blend_texture_view->texture);
+   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);
-   util_blit_pixels_tex(ctx->blit,
-                        view,
-                        0, 0,
-                        strb->width, strb->height,
-                        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;
+
+   matrix_mult(mat, &tmp);
 
-   return ctx->texture_vs->driver;
+   return VG_TRUE;
 }