d3dx9: Implement D3DXAssembleShaderFromFile.

This commit is contained in:
Matteo Bruni 2010-07-28 17:32:42 +02:00 committed by Alexandre Julliard
parent 2a62616ac7
commit 1b3376982d
2 changed files with 148 additions and 29 deletions

View File

@ -309,8 +309,8 @@ static char *wpp_lookup_mem(const char *filename, const char *parent_name,
}
path = malloc(strlen(filename) + 1);
if(!path) return NULL;
memcpy(path, filename, strlen(filename) + 1);
if(path)
memcpy(path, filename, strlen(filename) + 1);
return path;
}
@ -636,6 +636,79 @@ cleanup:
return hr;
}
/* D3DXInclude private implementation, used to implement
D3DXAssembleShaderFromFile from D3DXAssembleShader */
/* To be able to correctly resolve include search paths we have to store
the pathname of each include file. We store the pathname pointer right
before the file data. */
static HRESULT WINAPI d3dincludefromfile_open(ID3DXInclude *iface,
D3DXINCLUDE_TYPE include_type,
LPCSTR filename, LPCVOID parent_data,
LPCVOID *data, UINT *bytes) {
const char *p, *parent_name = "";
char *pathname = NULL;
char **buffer = NULL;
HANDLE file;
UINT size;
if(parent_data != NULL)
parent_name = *((const char **)parent_data - 1);
TRACE("Looking up for include file %s, parent %s\n", debugstr_a(filename), debugstr_a(parent_name));
if ((p = strrchr(parent_name, '\\')) || (p = strrchr(parent_name, '/'))) p++;
else p = parent_name;
pathname = HeapAlloc(GetProcessHeap(), 0, (p - parent_name) + strlen(filename) + 1);
if(!pathname)
return HRESULT_FROM_WIN32(GetLastError());
memcpy(pathname, parent_name, p - parent_name);
strcpy(pathname + (p - parent_name), filename);
file = CreateFileA(pathname, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, 0, 0);
if(file == INVALID_HANDLE_VALUE)
goto error;
TRACE("Include file found at pathname = %s\n", debugstr_a(pathname));
size = GetFileSize(file, NULL);
if(size == INVALID_FILE_SIZE)
goto error;
buffer = HeapAlloc(GetProcessHeap(), 0, size + sizeof(char *));
if(!buffer)
goto error;
*buffer = pathname;
if(!ReadFile(file, buffer + 1, size, bytes, NULL))
goto error;
*data = buffer + 1;
CloseHandle(file);
return S_OK;
error:
CloseHandle(file);
HeapFree(GetProcessHeap(), 0, pathname);
HeapFree(GetProcessHeap(), 0, buffer);
return HRESULT_FROM_WIN32(GetLastError());
}
static HRESULT WINAPI d3dincludefromfile_close(ID3DXInclude *iface, LPCVOID data) {
HeapFree(GetProcessHeap(), 0, *((char **)data - 1));
HeapFree(GetProcessHeap(), 0, (char **)data - 1);
return S_OK;
}
static const struct ID3DXIncludeVtbl D3DXInclude_Vtbl = {
d3dincludefromfile_open,
d3dincludefromfile_close
};
struct D3DXIncludeImpl {
const ID3DXIncludeVtbl *lpVtbl;
};
HRESULT WINAPI D3DXAssembleShaderFromFileA(LPCSTR filename,
CONST D3DXMACRO* defines,
LPD3DXINCLUDE include,
@ -667,8 +740,25 @@ HRESULT WINAPI D3DXAssembleShaderFromFileW(LPCWSTR filename,
LPD3DXBUFFER* shader,
LPD3DXBUFFER* error_messages)
{
FIXME("(%s, %p, %p, %x, %p, %p): stub\n", debugstr_w(filename), defines, include, flags, shader, error_messages);
return D3DERR_INVALIDCALL;
void *buffer;
DWORD len;
HRESULT hr;
struct D3DXIncludeImpl includefromfile;
if(FAILED(map_view_of_file(filename, &buffer, &len)))
return D3DXERR_INVALIDDATA;
if(!include)
{
includefromfile.lpVtbl = &D3DXInclude_Vtbl;
include = (LPD3DXINCLUDE)&includefromfile;
}
hr = D3DXAssembleShader(buffer, len, defines, include, flags,
shader, error_messages);
UnmapViewOfFile(buffer);
return hr;
}
HRESULT WINAPI D3DXAssembleShaderFromResourceA(HMODULE module,

View File

@ -1561,6 +1561,19 @@ static void assembleshader_test(void) {
"#include \"incl2.vsh\"\n"
"mov REGISTER, v0\n"
};
const char testshader3[] = {
"#include \"include/incl3.vsh\"\n"
"mov REGISTER, v0\n"
};
const char testincl3[] = {
"#include \"incl4.vsh\"\n"
};
const char testincl4_ok[] = {
"vs.1.1\n"
};
const char testincl4_wrong[] = {
"#error \"wrong include\"\n"
};
HRESULT hr;
LPD3DXBUFFER shader, messages;
D3DXMACRO defines[] = {
@ -1575,7 +1588,7 @@ static void assembleshader_test(void) {
}
};
struct D3DXIncludeImpl include;
HRESULT shader_vsh_res, incl_vsh_res;
HRESULT shader_vsh_res;
/* pDefines test */
shader = NULL;
@ -1649,25 +1662,22 @@ static void assembleshader_test(void) {
}
if(shader) ID3DXBuffer_Release(shader);
todo_wine {
shader_vsh_res = create_file("shader.vsh", testshader, sizeof(testshader));
if(SUCCEEDED(shader_vsh_res)) {
incl_vsh_res = create_file("incl.vsh", testincl, sizeof(testincl));
if(SUCCEEDED(incl_vsh_res)) {
/* D3DXAssembleShaderFromFile + #include test */
shader = NULL;
messages = NULL;
hr = D3DXAssembleShaderFromFileA("shader.vsh",
NULL, NULL, D3DXSHADER_SKIPVALIDATION,
&shader, &messages);
ok(hr == D3D_OK, "D3DXAssembleShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
if(messages) {
trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
ID3DXBuffer_Release(messages);
}
if(shader) ID3DXBuffer_Release(shader);
} else skip("Couldn't create \"incl.vsh\"\n");
create_file("incl.vsh", testincl, sizeof(testincl));
/* D3DXAssembleShaderFromFile + #include test */
shader = NULL;
messages = NULL;
hr = D3DXAssembleShaderFromFileA("shader.vsh",
NULL, NULL, D3DXSHADER_SKIPVALIDATION,
&shader, &messages);
ok(hr == D3D_OK, "D3DXAssembleShaderFromFile test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
if(messages) {
trace("D3DXAssembleShader messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
ID3DXBuffer_Release(messages);
}
if(shader) ID3DXBuffer_Release(shader);
/* D3DXAssembleShaderFromFile + pInclude test */
shader = NULL;
@ -1681,9 +1691,27 @@ static void assembleshader_test(void) {
ID3DXBuffer_Release(messages);
}
if(shader) ID3DXBuffer_Release(shader);
} else skip("Couldn't create \"shader.vsh\"\n");
} /* todo_wine */
create_file("shader3.vsh", testshader3, sizeof(testshader3));
create_file("incl4.vsh", testincl4_wrong, sizeof(testincl4_wrong));
if(CreateDirectoryA("include", NULL)) {
create_file("include/incl3.vsh", testincl3, sizeof(testincl3));
create_file("include/incl4.vsh", testincl4_ok, sizeof(testincl4_ok));
/* path search #include test */
shader = NULL;
messages = NULL;
hr = D3DXAssembleShaderFromFileA("shader3.vsh", NULL, NULL,
D3DXSHADER_SKIPVALIDATION,
&shader, &messages);
ok(hr == D3D_OK, "D3DXAssembleShaderFromFile path search test failed with error 0x%x - %d\n", hr, hr & 0x0000FFFF);
if(messages) {
trace("D3DXAssembleShaderFromFile path search messages:\n%s", (char *)ID3DXBuffer_GetBufferPointer(messages));
ID3DXBuffer_Release(messages);
}
if(shader) ID3DXBuffer_Release(shader);
} else skip("Couldn't create \"include\" directory\n");
} else skip("Couldn't create \"shader.vsh\"\n");
/* NULL shader tests */
shader = NULL;
@ -1698,8 +1726,6 @@ static void assembleshader_test(void) {
}
if(shader) ID3DXBuffer_Release(shader);
todo_wine {
shader = NULL;
messages = NULL;
hr = D3DXAssembleShaderFromFileA("nonexistent.vsh",
@ -1714,8 +1740,6 @@ static void assembleshader_test(void) {
}
if(shader) ID3DXBuffer_Release(shader);
} /* end of todo_wine */
/* D3DXAssembleShaderFromResource test */
shader = NULL;
messages = NULL;
@ -1745,7 +1769,12 @@ static void assembleshader_test(void) {
/* cleanup */
if(SUCCEEDED(shader_vsh_res)) {
DeleteFileA("shader.vsh");
if(SUCCEEDED(incl_vsh_res)) DeleteFileA("incl.vsh");
DeleteFileA("incl.vsh");
DeleteFileA("shader3.vsh");
DeleteFileA("incl4.vsh");
DeleteFileA("include/incl3.vsh");
DeleteFileA("include/incl4.vsh");
RemoveDirectoryA("include");
}
}