[g3dvl] move compositor creation and handling directly into the state trackers
[mesa.git] / src / gallium / state_trackers / vega / image.c
index 172311851e993d88104b4b404247394a5079f33f..44480876b6e7f2fb9db62687c021b6fdccd251a6 100644 (file)
 #include "renderer.h"
 #include "util_array.h"
 #include "api_consts.h"
-#include "shaders_cache.h"
 #include "shader.h"
 
 #include "pipe/p_context.h"
 #include "pipe/p_screen.h"
-#include "pipe/p_inlines.h"
-#include "util/u_blit.h"
+#include "util/u_inlines.h"
+#include "util/u_format.h"
 #include "util/u_tile.h"
 #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)
 {
    switch(format) {
    case VG_sRGB_565:
-      return PIPE_FORMAT_R5G6B5_UNORM;
+      return PIPE_FORMAT_B5G6R5_UNORM;
    case VG_sRGBA_5551:
-      return PIPE_FORMAT_A1R5G5B5_UNORM;
+      return PIPE_FORMAT_B5G5R5A1_UNORM;
    case VG_sRGBA_4444:
-      return PIPE_FORMAT_A4R4G4B4_UNORM;
+      return PIPE_FORMAT_B4G4R4A4_UNORM;
    case VG_sL_8:
    case VG_lL_8:
       return PIPE_FORMAT_L8_UNORM;
    case VG_BW_1:
-      return PIPE_FORMAT_A8R8G8B8_UNORM;
+      return PIPE_FORMAT_B8G8R8A8_UNORM;
    case VG_A_8:
       return PIPE_FORMAT_A8_UNORM;
 #ifdef OPENVG_VERSION_1_1
@@ -65,7 +66,7 @@ static enum pipe_format vg_format_to_pipe(VGImageFormat format)
       return PIPE_FORMAT_A8_UNORM;
 #endif
    default:
-      return PIPE_FORMAT_A8R8G8B8_UNORM;
+      return PIPE_FORMAT_B8G8R8A8_UNORM;
    }
 }
 
@@ -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_texture *dst, VGint dx, VGint dy,
-                            struct pipe_texture *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->width0;
-   src_bounds[3] = src->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) {
@@ -215,9 +204,9 @@ void vg_copy_surface(struct vg_context *ctx,
 
 }
 
-static struct pipe_texture *image_texture(struct vg_image *img)
+static struct pipe_resource *image_texture(struct vg_image *img)
 {
-   struct pipe_texture *tex = img->texture;
+   struct pipe_resource *tex = img->sampler_view->texture;
    return tex;
 }
 
@@ -246,9 +235,12 @@ struct vg_image * image_create(VGImageFormat format,
                                VGint width, VGint height)
 {
    struct vg_context *ctx = vg_current_context();
+   struct pipe_context *pipe = ctx->pipe;
    struct vg_image *image = CALLOC_STRUCT(vg_image);
    enum pipe_format pformat = vg_format_to_pipe(format);
-   struct pipe_texture pt, *newtex;
+   struct pipe_resource pt, *newtex;
+   struct pipe_sampler_view view_templ;
+   struct pipe_sampler_view *view;
    struct pipe_screen *screen = ctx->pipe->screen;
 
    vg_init_object(&image->base, ctx, VG_OBJECT_IMAGE);
@@ -265,7 +257,7 @@ struct vg_image * image_create(VGImageFormat format,
    image->sampler.normalized_coords = 1;
 
    assert(screen->is_format_supported(screen, pformat, PIPE_TEXTURE_2D,
-                                      PIPE_TEXTURE_USAGE_SAMPLER, 0));
+                                      0, PIPE_BIND_SAMPLER_VIEW));
 
    memset(&pt, 0, sizeof(pt));
    pt.target = PIPE_TEXTURE_2D;
@@ -274,13 +266,26 @@ struct vg_image * image_create(VGImageFormat format,
    pt.width0 = width;
    pt.height0 = height;
    pt.depth0 = 1;
-   pt.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER;
+   pt.array_size = 1;
+   pt.bind = PIPE_BIND_SAMPLER_VIEW;
 
-   newtex = screen->texture_create(screen, &pt);
+   newtex = screen->resource_create(screen, &pt);
 
    debug_assert(newtex);
 
-   image->texture = 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);
+
+   image->sampler_view = view;
 
    vg_context_add_object(ctx, VG_OBJECT_IMAGE, image);
 
@@ -344,8 +349,10 @@ void image_destroy(struct vg_image *img)
       array_destroy(img->children_array);
    }
 
-   pipe_texture_reference(&img->texture, NULL);
-   free(img);
+   vg_free_object(&img->base);
+
+   pipe_sampler_view_reference(&img->sampler_view, NULL);
+   FREE(img);
 }
 
 void image_clear(struct vg_image *img,
@@ -377,8 +384,8 @@ void image_sub_data(struct vg_image *image,
    VGfloat *df = (VGfloat*)temp;
    VGint i;
    struct vg_context *ctx = vg_current_context();
-   struct pipe_screen *screen = ctx->pipe->screen;
-   struct pipe_texture *texture = image_texture(image);
+   struct pipe_context *pipe = ctx->pipe;
+   struct pipe_resource *texture = image_texture(image);
    VGint xoffset = 0, yoffset = 0;
 
    if (x < 0) {
@@ -411,17 +418,17 @@ void image_sub_data(struct vg_image *image,
    }
 
    { /* upload color_data */
-      struct pipe_transfer *transfer = screen->get_tex_transfer(
-         screen, texture, 0, 0, 0,
+      struct pipe_transfer *transfer = pipe_get_transfer(
+         pipe, texture, 0, 0,
          PIPE_TRANSFER_WRITE, 0, 0, texture->width0, texture->height0);
       src += (dataStride * yoffset);
       for (i = 0; i < height; i++) {
          _vega_unpack_float_span_rgba(ctx, width, xoffset, src, dataFormat, temp);
-         pipe_put_tile_rgba(transfer, x+image->x, y+image->y, width, 1, df);
+         pipe_put_tile_rgba(pipe, transfer, x+image->x, y+image->y, width, 1, df);
          y += yStep;
          src += dataStride;
       }
-      screen->tex_transfer_destroy(transfer);
+      pipe->transfer_destroy(pipe, transfer);
    }
 }
 
@@ -434,7 +441,6 @@ void image_get_sub_data(struct vg_image * image,
 {
    struct vg_context *ctx = vg_current_context();
    struct pipe_context *pipe = ctx->pipe;
-   struct pipe_screen *screen = pipe->screen;
    VGfloat temp[VEGA_MAX_IMAGE_WIDTH][4];
    VGfloat *df = (VGfloat*)temp;
    VGint y = 0, yStep = 1;
@@ -443,24 +449,24 @@ void image_get_sub_data(struct vg_image * image,
 
    {
       struct pipe_transfer *transfer =
-         screen->get_tex_transfer(screen,
-                                  image->texture,  0, 0, 0,
-                                  PIPE_TRANSFER_READ,
-                                  0, 0,
-                                  image->x + image->width,
-                                  image->y + image->height);
+         pipe_get_transfer(pipe,
+                           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
          debug_printf("%d-%d  == %d\n", sy, height, y);
 #endif
-         pipe_get_tile_rgba(transfer, sx+image->x, y, width, 1, df);
+         pipe_get_tile_rgba(pipe, transfer, sx+image->x, y, width, 1, df);
          y += yStep;
          _vega_pack_rgba_span_float(ctx, width, temp, dataFormat, dst);
          dst += dataStride;
       }
 
-      screen->tex_transfer_destroy(transfer);
+      pipe->transfer_destroy(pipe, transfer);
    }
 }
 
@@ -478,9 +484,9 @@ struct vg_image * image_child_image(struct vg_image *parent,
    image->width = width;
    image->height = height;
    image->parent = parent;
-   image->texture = 0;
-   pipe_texture_reference(&image->texture,
-                          parent->texture);
+   image->sampler_view = NULL;
+   pipe_sampler_view_reference(&image->sampler_view,
+                               parent->sampler_view);
 
    image->sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
    image->sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE;
@@ -512,20 +518,24 @@ void image_copy(struct vg_image *dst, VGint dx, VGint dy,
       vg_set_error(ctx, VG_ILLEGAL_ARGUMENT_ERROR);
       return;
    }
-   /* make sure rendering has completed */
-   ctx->pipe->flush(ctx->pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
-   vg_copy_texture(ctx, dst->texture, dst->x + dx, dst->y + dy,
-                   src->texture, src->x + sx, src->y + sy, width, height);
+   vg_copy_texture(ctx, dst->sampler_view->texture, dst->x + dx, dst->y + 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;
@@ -536,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);
 
@@ -559,20 +564,18 @@ 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,
-                                  PIPE_BUFFER_USAGE_GPU_READ);
+   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,
@@ -581,19 +584,17 @@ 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 */
    /*dy = dst->height - dy - height;*/
 
-   /* make sure rendering has completed */
-   pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, NULL);
+   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);
 
-   surf = screen->get_tex_surface(screen, image_texture(dst),  0, 0, 0,
-                                  PIPE_BUFFER_USAGE_GPU_WRITE |
-                                  PIPE_BUFFER_USAGE_GPU_READ);
    vg_copy_surface(ctx, surf, dst->x + dx, dst->y + dy,
                    strb->surface, sx, sy, width, height);
 
@@ -624,12 +625,12 @@ VGboolean vg_image_overlaps(struct vg_image *dst,
 }
 
 VGint image_bind_samplers(struct vg_image *img, struct pipe_sampler_state **samplers,
-                          struct pipe_texture **textures)
+                          struct pipe_sampler_view **sampler_views)
 {
    img->sampler.min_img_filter = image_sampler_filter(img->base.ctx);
    img->sampler.mag_img_filter = image_sampler_filter(img->base.ctx);
    samplers[3] = &img->sampler;
-   textures[3] = img->texture;
+   sampler_views[3] = img->sampler_view;
    return 1;
 }
 
@@ -643,7 +644,7 @@ VGint image_sampler_filter(struct vg_context *ctx)
        return PIPE_TEX_FILTER_NEAREST;
        break;
     case VG_IMAGE_QUALITY_BETTER:
-       /*return PIPE_TEX_FILTER_ANISO;*/
+       /* possibly use anisotropic filtering */
        return PIPE_TEX_FILTER_LINEAR;
        break;
     default: