[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 ¤t_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 != ¤t_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