From 90de12a47e26ccc0b4cc8189c76991609481870d Mon Sep 17 00:00:00 2001
From: Gwenole Beauchesne <gbeauchesne@splitted-desktop.com>
Date: Wed, 4 Nov 2009 17:34:53 +0000
Subject: [PATCH] [G45] Handle cliprects in vaPutSurface().

---
 i965_drv_video/i965_drv_video.c |   39 ++++--
 i965_drv_video/i965_render.c    |  284 +++++++++++++++++++--------------------
 i965_drv_video/i965_render.h    |   30 ++---
 3 files changed, 176 insertions(+), 177 deletions(-)

diff --git a/i965_drv_video/i965_drv_video.c b/i965_drv_video/i965_drv_video.c
index e8f638c..20d6bab 100644
--- a/i965_drv_video/i965_drv_video.c
+++ b/i965_drv_video/i965_drv_video.c
@@ -1507,13 +1507,23 @@ i965_PutSurface(VADriverContextP ctx,
     union dri_buffer *buffer;
     struct intel_region *dest_region;
     struct object_surface *obj_surface; 
-	int ret;
+    int ret;
     uint32_t name;
+    VARectangle src_rect, dst_rect;
     Bool new_region = False;
+
     /* Currently don't support DRI1 */
     if (dri_state->driConnectedFlag != VA_DRI2)
         return VA_STATUS_ERROR_UNKNOWN;
 
+    /* XXX: we currently only support up to 64 cliprects */
+    if (number_cliprects > MAX_CLIP_RECTS)
+        return VA_STATUS_ERROR_OPERATION_FAILED;
+
+    obj_surface = SURFACE(surface);
+    if (!obj_surface)
+        return VA_STATUS_ERROR_INVALID_SURFACE;
+
     dri_drawable = dri_get_drawable(ctx, draw);
     assert(dri_drawable);
 
@@ -1552,17 +1562,24 @@ i965_PutSurface(VADriverContextP ctx,
         assert(ret == 0);
     }
 
-    i965_render_put_surface(ctx, surface,
-                            srcx, srcy, srcw, srch,
-                            destx, desty, destw, desth);
-    obj_surface = SURFACE(surface);
-    if(obj_surface->subpic != VA_INVALID_ID) {	
-	i965_render_put_subpic(ctx, surface,
-                           srcx, srcy, srcw, srch,
-                           destx, desty, destw, desth);
-    } 
-    dri_swap_buffer(ctx, dri_drawable);
+    src_rect.x      = srcx;
+    src_rect.y      = srcy;
+    src_rect.width  = srcw;
+    src_rect.height = srch;
+
+    dst_rect.x      = destx;
+    dst_rect.y      = desty;
+    dst_rect.width  = destw;
+    dst_rect.height = desth;
 
+    i965_render_put_surface(ctx, surface, &src_rect, &dst_rect,
+                            cliprects, number_cliprects);
+
+    if (obj_surface->subpic != VA_INVALID_ID)
+	i965_render_put_subpic(ctx, surface, &src_rect, &dst_rect,
+                               cliprects, number_cliprects);
+
+    dri_swap_buffer(ctx, dri_drawable);
     return VA_STATUS_SUCCESS;
 }
 
diff --git a/i965_drv_video/i965_render.c b/i965_drv_video/i965_render.c
index 0476087..d7cd8fe 100644
--- a/i965_drv_video/i965_render.c
+++ b/i965_drv_video/i965_render.c
@@ -787,13 +787,81 @@ i965_render_binding_table(VADriverContextP ctx)
     dri_bo_unmap(render_state->wm.binding_table);
 }
 
-static void 
+static unsigned int
+i965_render_do_upload_vertex(VADriverContextP   ctx,
+                             unsigned int       width,
+                             unsigned int       height,
+                             const VARectangle *src_rect,
+                             const VARectangle *dst_rect,
+                             const VARectangle *cliprects,
+                             unsigned int       num_cliprects)
+{
+    struct i965_driver_data *i965 = i965_driver_data(ctx);
+    struct i965_render_state *render_state = &i965->render_state;
+    struct intel_region *dest_region = render_state->draw_region;
+    float *vb, tx1, tx2, ty1, ty2;
+    int x1, x2, y1, y2;
+    unsigned int i, n;
+
+    if (!cliprects || num_cliprects == 0) {
+        cliprects = dst_rect;
+        num_cliprects = 1;
+    }
+
+    dri_bo_map(render_state->vb.vertex_buffer, 1);
+    assert(render_state->vb.vertex_buffer->virtual);
+    vb = render_state->vb.vertex_buffer->virtual;
+
+    for (n = 0, i = 0; i < num_cliprects; i++) {
+        x1 = dest_region->x + cliprects[i].x;
+        y1 = dest_region->y + cliprects[i].y;
+        x2 = x1 + cliprects[i].width;
+        y2 = y1 + cliprects[i].height;
+        x1 = MAX(x1, dst_rect->x);
+        y1 = MAX(y1, dst_rect->y);
+        x2 = MIN(x2, dst_rect->x + dst_rect->width);
+        y2 = MIN(y2, dst_rect->y + dst_rect->height);
+
+        if (x2 <= x1 || y2 <= y1)
+            continue;
+
+        const float sx1 = (float)(x1 - dst_rect->x) / (float)dst_rect->width;
+        const float sy1 = (float)(y1 - dst_rect->y) / (float)dst_rect->height;
+        const float sx2 = (float)(x2 - dst_rect->x) / (float)dst_rect->width;
+        const float sy2 = (float)(y2 - dst_rect->y) / (float)dst_rect->height;
+        tx1 = ((float)src_rect->x + sx1 * (float)src_rect->width) / width;
+        ty1 = ((float)src_rect->y + sy1 * (float)src_rect->height) / height;
+        tx2 = ((float)src_rect->x + sx2 * (float)src_rect->width) / width;
+        ty2 = ((float)src_rect->y + sy2 * (float)src_rect->height) / height;
+
+        vb[n++] = tx2;
+        vb[n++] = ty2;
+        vb[n++] = x2;
+        vb[n++] = y2;
+
+        vb[n++] = tx1;
+        vb[n++] = ty2;
+        vb[n++] = x1;
+        vb[n++] = y2;
+
+        vb[n++] = tx1;
+        vb[n++] = ty1;
+        vb[n++] = x1;
+        vb[n++] = y1;
+    }
+
+    dri_bo_unmap(render_state->vb.vertex_buffer);
+    return n / 12;
+}
+
+static unsigned int
 i965_subpic_render_upload_vertex(VADriverContextP ctx,
                                  VASurfaceID surface,
-                                 const VARectangle *output_rect)
-{    
+                                 const VARectangle *output_rect,
+                                 const VARectangle *cliprects,
+                                 unsigned int num_cliprects)
+{
     struct i965_driver_data  *i965         = i965_driver_data(ctx);
-    struct i965_render_state *render_state = &i965->render_state;
     struct object_surface    *obj_surface  = SURFACE(surface);
     struct object_subpic     *obj_subpic   = SUBPIC(obj_surface->subpic);
 
@@ -803,8 +871,6 @@ i965_subpic_render_upload_vertex(VADriverContextP ctx,
     const float ssy = (float)output_rect->height / (float)obj_surface->height;
     const float sx  = psx * ssx;
     const float sy  = psy * ssy;
-    float *vb, tx1, tx2, ty1, ty2, x1, x2, y1, y2;
-    int i = 0;
 
     VARectangle dst_rect;
     dst_rect.x      = output_rect->x + sx * (float)obj_subpic->dst_rect.x;
@@ -812,106 +878,38 @@ i965_subpic_render_upload_vertex(VADriverContextP ctx,
     dst_rect.width  = sx * (float)obj_subpic->dst_rect.width;
     dst_rect.height = sy * (float)obj_subpic->dst_rect.height;
 
-    dri_bo_map(render_state->vb.vertex_buffer, 1);
-    assert(render_state->vb.vertex_buffer->virtual);
-    vb = render_state->vb.vertex_buffer->virtual;
-
-    tx1 = (float)obj_subpic->src_rect.x / (float)obj_subpic->width;
-    ty1 = (float)obj_subpic->src_rect.y / (float)obj_subpic->height;
-    tx2 = (float)(obj_subpic->src_rect.x + obj_subpic->src_rect.width) / (float)obj_subpic->width;
-    ty2 = (float)(obj_subpic->src_rect.y + obj_subpic->src_rect.height) / (float)obj_subpic->height;
-
-    x1 = (float)dst_rect.x;
-    y1 = (float)dst_rect.y;
-    x2 = (float)(dst_rect.x + dst_rect.width);
-    y2 = (float)(dst_rect.y + dst_rect.height);
-
-    vb[i++] = tx2;
-    vb[i++] = ty2;
-    vb[i++] = x2;
-    vb[i++] = y2;
-
-    vb[i++] = tx1;
-    vb[i++] = ty2;
-    vb[i++] = x1;
-    vb[i++] = y2;
-
-    vb[i++] = tx1;
-    vb[i++] = ty1;
-    vb[i++] = x1;
-    vb[i++] = y1;
-    dri_bo_unmap(render_state->vb.vertex_buffer);
+    return i965_render_do_upload_vertex(ctx,
+                                        obj_subpic->width, obj_subpic->height,
+                                        &obj_subpic->src_rect, &dst_rect,
+                                        cliprects, num_cliprects);
 }
 
-static void 
+static unsigned int 
 i965_render_upload_vertex(VADriverContextP ctx,
                           VASurfaceID surface,
-                          short srcx,
-                          short srcy,
-                          unsigned short srcw,
-                          unsigned short srch,
-                          short destx,
-                          short desty,
-                          unsigned short destw,
-                          unsigned short desth)
+                          const VARectangle *src_rect,
+                          const VARectangle *dst_rect,
+                          const VARectangle *cliprects,
+                          unsigned int num_cliprects)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
-    struct i965_render_state *render_state = &i965->render_state;
-    struct intel_region *dest_region = render_state->draw_region;
-    struct object_surface *obj_surface;
-    float *vb;
-
-    float u1, v1, u2, v2;
-    int i, width, height;
-    int box_x1 = dest_region->x + destx;
-    int box_y1 = dest_region->y + desty;
-    int box_x2 = box_x1 + destw;
-    int box_y2 = box_y1 + desth;
-
-    obj_surface = SURFACE(surface);
-    assert(surface);
-    width = obj_surface->width;
-    height = obj_surface->height;
-
-    u1 = (float)srcx / width;
-    v1 = (float)srcy / height;
-    u2 = (float)(srcx + srcw) / width;
-    v2 = (float)(srcy + srch) / height;
-
-    dri_bo_map(render_state->vb.vertex_buffer, 1);
-    assert(render_state->vb.vertex_buffer->virtual);
-    vb = render_state->vb.vertex_buffer->virtual;
-
-    i = 0;
-    vb[i++] = u2;
-    vb[i++] = v2;
-    vb[i++] = (float)box_x2;
-    vb[i++] = (float)box_y2;
-    
-    vb[i++] = u1;
-    vb[i++] = v2;
-    vb[i++] = (float)box_x1;
-    vb[i++] = (float)box_y2;
-
-    vb[i++] = u1;
-    vb[i++] = v1;
-    vb[i++] = (float)box_x1;
-    vb[i++] = (float)box_y1;
+    struct object_surface *obj_surface = SURFACE(surface);
+    assert(obj_surface);
 
-    dri_bo_unmap(render_state->vb.vertex_buffer);
+    return i965_render_do_upload_vertex(ctx,
+                                        obj_surface->width, obj_surface->height,
+                                        src_rect,
+                                        dst_rect,
+                                        cliprects, num_cliprects);
 }
 
-static void
+static unsigned int
 i965_surface_render_state_setup(VADriverContextP ctx,
-                        VASurfaceID surface,
-                        short srcx,
-                        short srcy,
-                        unsigned short srcw,
-                        unsigned short srch,
-                        short destx,
-                        short desty,
-                        unsigned short destw,
-                        unsigned short desth)
+                                VASurfaceID surface,
+                                const VARectangle *src_rect,
+                                const VARectangle *dst_rect,
+                                const VARectangle *cliprects,
+                                unsigned int num_cliprects)
 {
     i965_render_vs_unit(ctx);
     i965_render_sf_unit(ctx);
@@ -922,21 +920,17 @@ i965_surface_render_state_setup(VADriverContextP ctx,
     i965_render_cc_viewport(ctx);
     i965_render_cc_unit(ctx);
     i965_render_binding_table(ctx);
-    i965_render_upload_vertex(ctx, surface,
-                              srcx, srcy, srcw, srch,
-                              destx, desty, destw, desth);
+    return i965_render_upload_vertex(ctx, surface, src_rect, dst_rect,
+                                     cliprects, num_cliprects);
 }
-static void
+
+static unsigned int
 i965_subpic_render_state_setup(VADriverContextP ctx,
-                        VASurfaceID surface,
-                        short srcx,
-                        short srcy,
-                        unsigned short srcw,
-                        unsigned short srch,
-                        short destx,
-                        short desty,
-                        unsigned short destw,
-                        unsigned short desth)
+                               VASurfaceID surface,
+                               const VARectangle *src_rect,
+                               const VARectangle *dst_rect,
+                               const VARectangle *cliprects,
+                               unsigned int num_cliprects)
 {
     i965_render_vs_unit(ctx);
     i965_render_sf_unit(ctx);
@@ -947,16 +941,10 @@ i965_subpic_render_state_setup(VADriverContextP ctx,
     i965_render_cc_viewport(ctx);
     i965_subpic_render_cc_unit(ctx);
     i965_render_binding_table(ctx);
-
-    VARectangle output_rect;
-    output_rect.x      = destx;
-    output_rect.y      = desty;
-    output_rect.width  = destw;
-    output_rect.height = desth;
-    i965_subpic_render_upload_vertex(ctx, surface, &output_rect);
+    return i965_subpic_render_upload_vertex(ctx, surface, dst_rect,
+                                            cliprects, num_cliprects);
 }
 
-
 static void
 i965_render_pipeline_select(VADriverContextP ctx)
 {
@@ -1192,7 +1180,7 @@ i965_render_upload_image_palette(
 }
 
 static void
-i965_render_startup(VADriverContextP ctx)
+i965_render_startup(VADriverContextP ctx, unsigned int vb_offset)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct i965_render_state *render_state = &i965->render_state;
@@ -1203,7 +1191,7 @@ i965_render_startup(VADriverContextP ctx)
               (0 << VB0_BUFFER_INDEX_SHIFT) |
               VB0_VERTEXDATA |
               ((4 * 4) << VB0_BUFFER_PITCH_SHIFT));
-    OUT_RELOC(ctx, render_state->vb.vertex_buffer, I915_GEM_DOMAIN_VERTEX, 0, 0);
+    OUT_RELOC(ctx, render_state->vb.vertex_buffer, I915_GEM_DOMAIN_VERTEX, 0, vb_offset);
 
     if (IS_IGDNG(i965->intel.device_id))
         OUT_RELOC(ctx, render_state->vb.vertex_buffer, I915_GEM_DOMAIN_VERTEX, 0, 12 * 4);
@@ -1268,8 +1256,10 @@ i965_clear_dest_region(VADriverContextP ctx)
 }
 
 static void
-i965_surface_render_pipeline_setup(VADriverContextP ctx)
+i965_surface_render_pipeline_setup(VADriverContextP ctx, unsigned int n_rects)
 {
+    unsigned int i;
+
     intel_batchbuffer_start_atomic(ctx, 0x1000);
     intel_batchbuffer_emit_mi_flush(ctx);
     i965_clear_dest_region(ctx);
@@ -1283,13 +1273,16 @@ i965_surface_render_pipeline_setup(VADriverContextP ctx)
     i965_render_cs_urb_layout(ctx);
     i965_render_drawing_rectangle(ctx);
     i965_render_vertex_elements(ctx);
-    i965_render_startup(ctx);
+    for (i = 0; i < n_rects; i++)
+        i965_render_startup(ctx, 48 * i);
     intel_batchbuffer_end_atomic(ctx);
 }
 
 static void
-i965_subpic_render_pipeline_setup(VADriverContextP ctx)
+i965_subpic_render_pipeline_setup(VADriverContextP ctx, unsigned int n_rects)
 {
+    unsigned int i;
+
     intel_batchbuffer_start_atomic(ctx, 0x1000);
     intel_batchbuffer_emit_mi_flush(ctx);
     i965_render_pipeline_select(ctx);
@@ -1302,7 +1295,8 @@ i965_subpic_render_pipeline_setup(VADriverContextP ctx)
     i965_render_cs_urb_layout(ctx);
     i965_render_drawing_rectangle(ctx);
     i965_render_vertex_elements(ctx);
-    i965_render_startup(ctx);
+    for (i = 0; i < n_rects; i++)
+        i965_render_startup(ctx, 48 * i);
     intel_batchbuffer_end_atomic(ctx);
 }
 
@@ -1396,45 +1390,39 @@ i965_render_initialize(VADriverContextP ctx)
 void
 i965_render_put_surface(VADriverContextP ctx,
                         VASurfaceID surface,
-                        short srcx,
-                        short srcy,
-                        unsigned short srcw,
-                        unsigned short srch,
-                        short destx,
-                        short desty,
-                        unsigned short destw,
-                        unsigned short desth)
+                        const VARectangle *src_rect,
+                        const VARectangle *dst_rect,
+                        const VARectangle *cliprects,
+                        unsigned int num_cliprects)
 {
+    unsigned int n_rects;
+
     i965_render_initialize(ctx);
-    i965_surface_render_state_setup(ctx, surface,
-                            srcx, srcy, srcw, srch,
-                            destx, desty, destw, desth);
-    i965_surface_render_pipeline_setup(ctx);
+    n_rects = i965_surface_render_state_setup(ctx, surface,
+                                              src_rect, dst_rect,
+                                              cliprects, num_cliprects);
+    i965_surface_render_pipeline_setup(ctx, n_rects);
     intel_batchbuffer_flush(ctx);
 }
 
 void
 i965_render_put_subpic(VADriverContextP ctx,
-                        VASurfaceID surface,
-                        short srcx,
-                        short srcy,
-                        unsigned short srcw,
-                        unsigned short srch,
-                        short destx,
-                        short desty,
-                        unsigned short destw,
-                        unsigned short desth)
+                       VASurfaceID surface,
+                       const VARectangle *src_rect,
+                       const VARectangle *dst_rect,
+                       const VARectangle *cliprects,
+                       unsigned int num_cliprects)
 {
     struct i965_driver_data *i965 = i965_driver_data(ctx);
     struct object_surface *obj_surface = SURFACE(surface);
     struct object_subpic *obj_subpic = SUBPIC(obj_surface->subpic);
+    unsigned int n_rects;
     assert(obj_subpic);
 
     i965_render_initialize(ctx);
-    i965_subpic_render_state_setup(ctx, surface,
-	    srcx, srcy, srcw, srch,
-	    destx, desty, destw, desth);
-    i965_subpic_render_pipeline_setup(ctx);
+    n_rects = i965_subpic_render_state_setup(ctx, surface, src_rect, dst_rect,
+                                             cliprects, num_cliprects);
+    i965_subpic_render_pipeline_setup(ctx, n_rects);
     i965_render_upload_image_palette(ctx, obj_subpic->image, 0xff);
     intel_batchbuffer_flush(ctx);
 }
diff --git a/i965_drv_video/i965_render.h b/i965_drv_video/i965_render.h
index e3dce02..d2e23f1 100644
--- a/i965_drv_video/i965_render.h
+++ b/i965_drv_video/i965_render.h
@@ -28,6 +28,7 @@
 #ifndef _I965_RENDER_H_
 #define _I965_RENDER_H_
 
+#define MAX_CLIP_RECTS          80 /* vb_bo:4096 / vb:(3*4*4) */
 #define MAX_RENDER_SURFACES     16
 #define MAX_SAMPLERS            16
 
@@ -65,27 +66,20 @@ struct i965_render_state
 
 Bool i965_render_init(VADriverContextP ctx);
 Bool i965_render_terminate(VADriverContextP ctx);
+
 void i965_render_put_surface(VADriverContextP ctx,
                              VASurfaceID surface,
-                             short srcx,
-                             short srcy,
-                             unsigned short srcw,
-                             unsigned short srch,
-                             short destx,
-                             short desty,
-                             unsigned short destw,
-                             unsigned short desth);
-
+                             const VARectangle *src_rect,
+                             const VARectangle *dst_rect,
+                             const VARectangle *cliprects,
+                             unsigned int num_cliprects);
 
 void
 i965_render_put_subpic(VADriverContextP ctx,
-                        VASurfaceID surface,
-                        short srcx,
-                        short srcy,
-                        unsigned short srcw,
-                        unsigned short srch,
-                        short destx,
-                        short desty,
-                        unsigned short destw,
-                        unsigned short desth);
+                       VASurfaceID surface,
+                       const VARectangle *src_rect,
+                       const VARectangle *dst_rect,
+                       const VARectangle *cliprects,
+                       unsigned int num_cliprects);
+
 #endif /* _I965_RENDER_H_ */
-- 
1.5.4.3

