Stefan Doesinger : wined3d: Implement break and breakc.

Alexandre Julliard julliard at winehq.org
Tue Jun 16 09:09:38 CDT 2009


Module: wine
Branch: master
Commit: dfefbcd00de49194876d5fd54efa9cc54ff84616
URL:    http://source.winehq.org/git/wine.git/?a=commit;h=dfefbcd00de49194876d5fd54efa9cc54ff84616

Author: Stefan Doesinger <stefan at codeweavers.com>
Date:   Wed Jun  3 07:39:29 2009 +0200

wined3d: Implement break and breakc.

---

 dlls/wined3d/arb_program_shader.c |   90 ++++++++++++++++++++++++++++++++++---
 1 files changed, 84 insertions(+), 6 deletions(-)

diff --git a/dlls/wined3d/arb_program_shader.c b/dlls/wined3d/arb_program_shader.c
index 144b694..0800540 100644
--- a/dlls/wined3d/arb_program_shader.c
+++ b/dlls/wined3d/arb_program_shader.c
@@ -77,7 +77,13 @@ static unsigned int reserved_vs_const(IWineD3DBaseShader *shader, const WineD3D_
 struct control_frame
 {
     struct                          list entry;
-    BOOL                            ifc;
+    enum
+    {
+        IF,
+        IFC,
+        LOOP,
+        REP
+    } type;
     BOOL                            muting;
     BOOL                            outer_loop;
     unsigned int                    loop_no;
@@ -2199,6 +2205,74 @@ static void shader_hw_endrep(const struct wined3d_shader_instruction *ins)
     }
 }
 
+static const struct control_frame *find_last_loop(const struct shader_arb_ctx_priv *priv)
+{
+    struct control_frame *control_frame;
+
+    LIST_FOR_EACH_ENTRY(control_frame, &priv->control_frames, struct control_frame, entry)
+    {
+        if(control_frame->type == LOOP || control_frame->type == REP) return control_frame;
+    }
+    ERR("Could not find loop for break\n");
+    return NULL;
+}
+
+static void shader_hw_break(const struct wined3d_shader_instruction *ins)
+{
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data);
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    if(vshader)
+    {
+        shader_addline(buffer, "BRA loop_%u_end;\n", control_frame->loop_no);
+    }
+    else
+    {
+        shader_addline(buffer, "BRK;\n");
+    }
+}
+
+static void shader_hw_breakc(const struct wined3d_shader_instruction *ins)
+{
+    SHADER_BUFFER *buffer = ins->ctx->buffer;
+    const struct control_frame *control_frame = find_last_loop(ins->ctx->backend_data);
+    char src_name0[50];
+    char src_name1[50];
+    const char *comp;
+    BOOL vshader = shader_is_vshader_version(ins->ctx->reg_maps->shader_version.type);
+
+    shader_arb_get_src_param(ins, &ins->src[0], 0, src_name0);
+    shader_arb_get_src_param(ins, &ins->src[1], 1, src_name1);
+
+    switch (ins->flags)
+    {
+        case COMPARISON_GT: comp = "GT"; break;
+        case COMPARISON_EQ: comp = "EQ"; break;
+        case COMPARISON_GE: comp = "GE"; break;
+        case COMPARISON_LT: comp = "LT"; break;
+        case COMPARISON_NE: comp = "NE"; break;
+        case COMPARISON_LE: comp = "LE"; break;
+        default:
+            FIXME("Unrecognized comparison value: %u\n", ins->flags);
+            comp = "(\?\?)";
+    }
+
+    if(vshader)
+    {
+        /* SUBC CC, src0, src1" works only in pixel shaders, so use TA to throw
+         * away the subtraction result
+         */
+        shader_addline(buffer, "SUBC TA, %s, %s;\n", src_name0, src_name1);
+        shader_addline(buffer, "BRA loop_%u_end (%s.x);\n", control_frame->loop_no, comp);
+    }
+    else
+    {
+        shader_addline(buffer, "SUBC CC, %s, %s;\n", src_name0, src_name1);
+        shader_addline(buffer, "BRK (%s.x);\n", comp);
+    }
+}
+
 static GLuint create_arb_blt_vertex_program(const WineD3D_GL_Info *gl_info)
 {
     GLuint program_id = 0;
@@ -3225,8 +3299,8 @@ static const SHADER_HANDLER shader_arb_instruction_handler_table[WINED3DSIH_TABL
     /* WINED3DSIH_ABS           */ shader_hw_map2gl,
     /* WINED3DSIH_ADD           */ shader_hw_map2gl,
     /* WINED3DSIH_BEM           */ pshader_hw_bem,
-    /* WINED3DSIH_BREAK         */ NULL,
-    /* WINED3DSIH_BREAKC        */ NULL,
+    /* WINED3DSIH_BREAK         */ shader_hw_break,
+    /* WINED3DSIH_BREAKC        */ shader_hw_breakc,
     /* WINED3DSIH_BREAKP        */ NULL,
     /* WINED3DSIH_CALL          */ NULL,
     /* WINED3DSIH_CALLNZ        */ NULL,
@@ -3483,6 +3557,9 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
         control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
         list_add_head(&priv->control_frames, &control_frame->entry);
 
+        if(ins->handler_idx == WINED3DSIH_LOOP) control_frame->type = LOOP;
+        if(ins->handler_idx == WINED3DSIH_REP) control_frame->type = REP;
+
         if(priv->target_version >= NV2)
         {
             control_frame->loop_no = priv->num_loops++;
@@ -3599,6 +3676,7 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
     {
         control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
         list_add_head(&priv->control_frames, &control_frame->entry);
+        control_frame->type = IF;
 
         if(!priv->muted && get_bool_const(ins, This, ins->src[0].reg.idx) == FALSE)
         {
@@ -3614,7 +3692,7 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
     {
         /* IF(bool) and if_cond(a, b) use the same ELSE and ENDIF tokens */
         control_frame = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(*control_frame));
-        control_frame->ifc = TRUE;
+        control_frame->type = IFC;
         list_add_head(&priv->control_frames, &control_frame->entry);
     }
     else if(ins->handler_idx == WINED3DSIH_ELSE)
@@ -3622,7 +3700,7 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
         struct list *e = list_head(&priv->control_frames);
         control_frame = LIST_ENTRY(e, struct control_frame, entry);
 
-        if(control_frame->ifc == FALSE)
+        if(control_frame->type == IF)
         {
             shader_addline(buffer, "#} else {\n");
             if(!priv->muted && !control_frame->muting)
@@ -3640,7 +3718,7 @@ static void shader_arb_handle_instruction(const struct wined3d_shader_instructio
         struct list *e = list_head(&priv->control_frames);
         control_frame = LIST_ENTRY(e, struct control_frame, entry);
 
-        if(!control_frame->ifc)
+        if(control_frame->type == IF)
         {
             shader_addline(buffer, "#} endif\n");
             if(control_frame->muting) priv->muted = FALSE;




More information about the wine-cvs mailing list