[15/18] d3dx9: Implement D3DXAssembleShader

Matteo Bruni matteo.mystral at gmail.com
Sun Aug 16 12:54:06 CDT 2009


-------------- next part --------------
From e63b6752b5d67003c88c922b6ed79b761b154b91 Mon Sep 17 00:00:00 2001
From: Matteo Bruni <matteo.mystral at gmail.com>
Date: Sun, 16 Aug 2009 17:09:51 +0200
Subject: d3dx9: Implement D3DXAssembleShader

---
 dlls/d3dx9_36/Makefile.in     |    1 +
 dlls/d3dx9_36/d3dx9_36.spec   |    2 +-
 dlls/d3dx9_36/d3dx9_36_main.c |    3 +
 dlls/d3dx9_36/shader.c        |  272 +++++++++++++++++++++++++++++++++++++++++
 4 files changed, 277 insertions(+), 1 deletions(-)

diff --git a/dlls/d3dx9_36/Makefile.in b/dlls/d3dx9_36/Makefile.in
index 87788d8..fd7f5ca 100644
--- a/dlls/d3dx9_36/Makefile.in
+++ b/dlls/d3dx9_36/Makefile.in
@@ -5,6 +5,7 @@ VPATH     = @srcdir@
 MODULE    = d3dx9_36.dll
 IMPORTLIB = d3dx9
 IMPORTS   = d3d9 gdi32 user32 kernel32
+EXTRALIBS = $(LIBWPP) $(LIBPORT)
 
 C_SRCS = \
 	asmparser.c \
diff --git a/dlls/d3dx9_36/d3dx9_36.spec b/dlls/d3dx9_36/d3dx9_36.spec
index d3fe3ac..7afd10c 100644
--- a/dlls/d3dx9_36/d3dx9_36.spec
+++ b/dlls/d3dx9_36/d3dx9_36.spec
@@ -1,4 +1,4 @@
-@ stub D3DXAssembleShader
+@ stdcall D3DXAssembleShader(ptr long ptr ptr long ptr ptr)
 @ stub D3DXAssembleShaderFromFileA
 @ stub D3DXAssembleShaderFromFileW
 @ stub D3DXAssembleShaderFromResourceA
diff --git a/dlls/d3dx9_36/d3dx9_36_main.c b/dlls/d3dx9_36/d3dx9_36_main.c
index e9c7004..31221d4 100644
--- a/dlls/d3dx9_36/d3dx9_36_main.c
+++ b/dlls/d3dx9_36/d3dx9_36_main.c
@@ -32,6 +32,7 @@
 #include "winuser.h"
 
 #include "d3dx9.h"
+#include "d3dx9_36_private.h"
 
 /***********************************************************************
  * DllMain.
@@ -44,8 +45,10 @@ BOOL WINAPI DllMain(HINSTANCE inst, DWORD reason, LPVOID reserved)
         return FALSE; /* prefer native version */
     case DLL_PROCESS_ATTACH:
         DisableThreadLibraryCalls(inst);
+        InitializeCriticalSection(&mutex);
         break;
     case DLL_PROCESS_DETACH:
+        DeleteCriticalSection(&mutex);
         break;
     }
     return TRUE;
diff --git a/dlls/d3dx9_36/shader.c b/dlls/d3dx9_36/shader.c
index 48499ac..a6de032 100644
--- a/dlls/d3dx9_36/shader.c
+++ b/dlls/d3dx9_36/shader.c
@@ -1,5 +1,6 @@
 /*
  * Copyright 2008 Luis Busquets
+ * Copyright 2009 Matteo Bruni
  *
  * This library is free software; you can redistribute it and/or
  * modify it under the terms of the GNU Lesser General Public
@@ -21,7 +22,10 @@
 #include "wine/debug.h"
 #include "windef.h"
 #include "wingdi.h"
+#include "wine/unicode.h"
 #include "d3dx9.h"
+#include "wine/wpp.h"
+#include "d3dx9_36_private.h"
 
 WINE_DEFAULT_DEBUG_CHANNEL(d3dx);
 
@@ -131,3 +135,271 @@ LPCSTR WINAPI D3DXGetVertexShaderProfile(LPDIRECT3DDEVICE9 device)
 
     return NULL;
 }
+
+#define BUFFER_INITIAL_CAPACITY 256
+
+struct mem_file_desc
+{
+    char *buffer;
+    unsigned int size;
+    unsigned int pos;
+};
+
+struct mem_file_desc current_shader;
+LPD3DXINCLUDE current_include;
+char *wpp_output;
+int wpp_output_capacity, wpp_output_size;
+CRITICAL_SECTION mutex;
+
+char *wpp_lookup_mem( const char *filename, const char *parent_name,
+                      char **include_path, int include_path_count )
+{
+    /* Here we return always ok. We will maybe fail on the next wpp_open_mem */
+    char *path;
+
+    path = malloc(strlen(filename) + 1);
+    memcpy(path, filename, strlen(filename) + 1);
+    return path;
+}
+
+void *wpp_open_mem(const char *filename, int type)
+{
+    struct mem_file_desc *desc;
+
+    if(filename[0] == '\0') /* "" means to load the initial shader */
+    {
+        current_shader.pos = 0;
+        return &current_shader;
+    }
+    else
+    {
+        HRESULT hr;
+
+        if(current_include == NULL) return NULL;
+        desc = malloc(sizeof(struct mem_file_desc));
+        if(!desc)
+        {
+            ERR("Error allocating memory\n");
+            return NULL;
+        }
+        hr = ID3DXInclude_Open(current_include,
+                               type ? D3DXINC_SYSTEM : D3DXINC_LOCAL,
+                               filename, NULL, (LPCVOID *)&desc->buffer,
+                               &desc->size);
+        if(FAILED(hr))
+        {
+            free(desc);
+            return NULL;
+        }
+    }
+    desc->pos = 0;
+    return desc;
+}
+
+void wpp_close_mem( void *file )
+{
+    struct mem_file_desc *desc = file;
+
+    if(desc != &current_shader)
+    {
+        if(current_include == NULL)
+        {
+            ERR("current_include == NULL, desc == %p, buffer = %s\n",
+                desc, desc->buffer);
+            free(desc);
+            return;
+        }
+        ID3DXInclude_Close(current_include, desc->buffer);
+        free(desc);
+        return;
+    }
+    /* This is the main file */
+    free(desc->buffer);
+}
+
+int wpp_read_mem( void *file, char *buffer, unsigned int len )
+{
+    struct mem_file_desc *desc = file;
+
+    if(desc->pos + len > desc->size) len = desc->size - desc->pos;
+    memcpy(buffer, &desc->buffer[desc->pos], len);
+    desc->pos += len;
+    return len;
+}
+
+void wpp_write_mem( const char *buffer, unsigned int len )
+{
+    if(wpp_output_capacity == 0)
+    {
+        wpp_output = malloc( BUFFER_INITIAL_CAPACITY );
+        if(!wpp_output)
+        {
+            ERR("Error allocating memory\n");
+            return;
+        }
+        wpp_output_capacity = BUFFER_INITIAL_CAPACITY;
+    }
+    if(wpp_output_size + len > wpp_output_capacity)
+    {
+        while(wpp_output_size + len > wpp_output_capacity)
+        {
+            wpp_output_capacity *= 2;
+        }
+        wpp_output = realloc(wpp_output, wpp_output_capacity);
+        if(!wpp_output)
+        {
+            ERR("Error allocating memory\n");
+            return;
+        }
+    }
+    memcpy(wpp_output+wpp_output_size, buffer, len);
+    wpp_output_size += len;
+}
+
+void wpp_close_output()
+{
+    /* trim buffer to the effective size */
+    wpp_output = realloc(wpp_output, wpp_output_size + 1);
+    wpp_output[wpp_output_size]='\0';
+}
+
+HRESULT assemble_shader(char *preprocShader,
+                        LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs )
+{
+    struct bwriter_shader *shader;
+    char *messages = NULL;
+    HRESULT hr;
+    DWORD *res;
+    LPD3DXBUFFER buffer;
+    int size, i;
+
+    shader = SlAssembleShader(preprocShader, &messages);
+
+    if(messages)
+    {
+        TRACE("messages:\n");
+        TRACE("%s", messages);
+
+        TRACE("shader source:\n");
+        for(i=0;i<strlen(preprocShader);i++)
+        {
+            TRACE("%c",preprocShader[i]);
+        }
+
+        size = strlen(messages) + 1;
+        hr = D3DXCreateBuffer(size, &buffer);
+        if(FAILED(hr))
+        {
+            HeapFree(GetProcessHeap(), 0, messages);
+            free(preprocShader);
+            return D3DXERR_INVALIDDATA;
+        }
+        CopyMemory(ID3DXBuffer_GetBufferPointer(buffer), messages, size);
+        *ppErrorMsgs = buffer;
+
+        HeapFree(GetProcessHeap(), 0, messages);
+    }
+    free(preprocShader);
+
+    if(shader == NULL)
+    {
+        ERR("Asm reading failed\n");
+        return D3DXERR_INVALIDDATA;
+    }
+
+    hr = SlWriteBytecode(shader, 9, &res);
+    SlDeleteShader(shader);
+    if(FAILED(hr))
+    {
+        ERR("SlWriteBytecode failed with 0x%08x\n", hr);
+        return D3DXERR_INVALIDDATA;
+    }
+
+    size = HeapSize(GetProcessHeap(), 0, res);
+    hr = D3DXCreateBuffer(size, &buffer);
+    if(FAILED(hr))
+    {
+        HeapFree(GetProcessHeap(), 0, res);
+        return hr;
+    }
+    CopyMemory(ID3DXBuffer_GetBufferPointer(buffer),res,size);
+    *ppShader = buffer;
+
+    HeapFree(GetProcessHeap(), 0, res);
+
+    return D3D_OK;
+}
+
+HRESULT WINAPI D3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen,
+                                  CONST D3DXMACRO* pDefines,
+                                  LPD3DXINCLUDE pInclude,
+                                  DWORD Flags,
+                                  LPD3DXBUFFER* ppShader,
+                                  LPD3DXBUFFER* ppErrorMsgs)
+{
+    int ret;
+    HRESULT hr;
+
+    struct wpp_io_callback wpp_callback = {
+        wpp_lookup_mem,
+        wpp_open_mem,
+        wpp_close_mem,
+        wpp_read_mem,
+        wpp_write_mem
+    };
+
+    EnterCriticalSection(&mutex);
+
+    /* TODO: Flags */
+    if(Flags) FIXME("Flags: %x\n", Flags);
+
+    if(pDefines != NULL)
+    {
+        while(pDefines->Name != NULL)
+        {
+            wpp_add_define(pDefines->Name, pDefines->Definition);
+            pDefines++;
+        }
+    }
+    current_include = pInclude;
+
+    *ppShader = *ppErrorMsgs = NULL;
+    wpp_output_size = wpp_output_capacity = 0;
+
+    /* Preprocess shader */
+    wpp_set_callback(&wpp_callback);
+    wpp_set_exit_on_error(0);
+    current_shader.buffer = malloc(SrcDataLen + 1);
+    if(!current_shader.buffer)
+    {
+        ERR("Not enough free memory\n");
+        LeaveCriticalSection(&mutex);
+        return E_OUTOFMEMORY;
+    }
+    memcpy(current_shader.buffer, pSrcData, SrcDataLen);
+    current_shader.buffer[SrcDataLen] = '\0';
+    current_shader.size = SrcDataLen;
+
+    ret = wpp_parse("", NULL);
+    wpp_close_output();
+    if(ret)
+    {
+        int i;
+
+        TRACE("Error during shader preprocessing\n");
+        TRACE("shader source:\n");
+        for(i=0;i<strlen(pSrcData);i++)
+        {
+            TRACE("%c",pSrcData[i]);
+        }
+        TRACE("\n");
+
+        free(wpp_output);
+        LeaveCriticalSection(&mutex);
+        return D3DXERR_INVALIDDATA;
+    }
+
+    hr = assemble_shader(wpp_output, ppShader, ppErrorMsgs);
+    LeaveCriticalSection(&mutex);
+    return hr;
+}
-- 
1.6.3.3


More information about the wine-patches mailing list