📄 pixelshader.c
字号:
/*
* shaders implementation
*
* Copyright 2002-2003 Jason Edmeades
* Copyright 2002-2003 Raphael Junqueira
* Copyright 2004 Christian Costa
* Copyright 2005 Oliver Stieber
* Copyright 2006 Ivan Gyurdiev
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#include "config.h"
#include <math.h>
#include <stdio.h>
#include "wined3d_private.h"
WINE_DEFAULT_DEBUG_CHANNEL(d3d_shader);
#define GLINFO_LOCATION ((IWineD3DDeviceImpl *) This->baseShader.device)->adapter->gl_info
#if 0 /* Must not be 1 in cvs version */
# define PSTRACE(A) TRACE A
# define TRACE_VSVECTOR(name) TRACE( #name "=(%f, %f, %f, %f)\n", name.x, name.y, name.z, name.w)
#else
# define PSTRACE(A)
# define TRACE_VSVECTOR(name)
#endif
#define GLNAME_REQUIRE_GLSL ((const char *)1)
/* *******************************************
IWineD3DPixelShader IUnknown parts follow
******************************************* */
static HRESULT WINAPI IWineD3DPixelShaderImpl_QueryInterface(IWineD3DPixelShader *iface, REFIID riid, LPVOID *ppobj)
{
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
TRACE("(%p)->(%s,%p)\n",This,debugstr_guid(riid),ppobj);
if (IsEqualGUID(riid, &IID_IUnknown)
|| IsEqualGUID(riid, &IID_IWineD3DBase)
|| IsEqualGUID(riid, &IID_IWineD3DBaseShader)
|| IsEqualGUID(riid, &IID_IWineD3DPixelShader)) {
IUnknown_AddRef(iface);
*ppobj = This;
return S_OK;
}
*ppobj = NULL;
return E_NOINTERFACE;
}
static ULONG WINAPI IWineD3DPixelShaderImpl_AddRef(IWineD3DPixelShader *iface) {
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
TRACE("(%p) : AddRef increasing from %d\n", This, This->ref);
return InterlockedIncrement(&This->ref);
}
static ULONG WINAPI IWineD3DPixelShaderImpl_Release(IWineD3DPixelShader *iface) {
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
ULONG ref;
TRACE("(%p) : Releasing from %d\n", This, This->ref);
ref = InterlockedDecrement(&This->ref);
if (ref == 0) {
/* SetPixelShader does not AddRef. If the bound pixel shader is destroyed, the pointer in the stateblock remains
* unchanged. Drawing again will most likely crash, even on windows. A problem can occur if the application creates
* a new pixel shader which resides at the same address. Then SetPixelShader will think it is a NOP change, and won't
* dirtify the state.
*
* Do NOT call GetPixelShader here. This will addRef and cause a recursion. And do NOT set the pixel shader to NULL,
* Windows does not do that(Although no test exists since they'd crash randomly)
*/
if(iface == ((IWineD3DDeviceImpl *) This->baseShader.device)->stateBlock->pixelShader) {
IWineD3DDeviceImpl_MarkStateDirty((IWineD3DDeviceImpl *) This->baseShader.device, STATE_PIXELSHADER);
}
if (This->baseShader.shader_mode == SHADER_GLSL && This->baseShader.prgId != 0) {
struct list *linked_programs = &This->baseShader.linked_programs;
TRACE("Deleting linked programs\n");
if (linked_programs->next) {
struct glsl_shader_prog_link *entry, *entry2;
LIST_FOR_EACH_ENTRY_SAFE(entry, entry2, linked_programs, struct glsl_shader_prog_link, pshader_entry) {
delete_glsl_program_entry(This->baseShader.device, entry);
}
}
TRACE("Deleting shader object %u\n", This->baseShader.prgId);
GL_EXTCALL(glDeleteObjectARB(This->baseShader.prgId));
checkGLcall("glDeleteObjectARB");
}
shader_delete_constant_list(&This->baseShader.constantsF);
shader_delete_constant_list(&This->baseShader.constantsB);
shader_delete_constant_list(&This->baseShader.constantsI);
HeapFree(GetProcessHeap(), 0, This);
}
return ref;
}
/* *******************************************
IWineD3DPixelShader IWineD3DPixelShader parts follow
******************************************* */
static HRESULT WINAPI IWineD3DPixelShaderImpl_GetParent(IWineD3DPixelShader *iface, IUnknown** parent){
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
*parent = This->parent;
IUnknown_AddRef(*parent);
TRACE("(%p) : returning %p\n", This, *parent);
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DPixelShaderImpl_GetDevice(IWineD3DPixelShader* iface, IWineD3DDevice **pDevice){
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)iface;
IWineD3DDevice_AddRef(This->baseShader.device);
*pDevice = This->baseShader.device;
TRACE("(%p) returning %p\n", This, *pDevice);
return WINED3D_OK;
}
static HRESULT WINAPI IWineD3DPixelShaderImpl_GetFunction(IWineD3DPixelShader* impl, VOID* pData, UINT* pSizeOfData) {
IWineD3DPixelShaderImpl *This = (IWineD3DPixelShaderImpl *)impl;
TRACE("(%p) : pData(%p), pSizeOfData(%p)\n", This, pData, pSizeOfData);
if (NULL == pData) {
*pSizeOfData = This->baseShader.functionLength;
return WINED3D_OK;
}
if (*pSizeOfData < This->baseShader.functionLength) {
/* MSDN claims (for d3d8 at least) that if *pSizeOfData is smaller
* than the required size we should write the required size and
* return D3DERR_MOREDATA. That's not actually true. */
return WINED3DERR_INVALIDCALL;
}
if (NULL == This->baseShader.function) { /* no function defined */
TRACE("(%p) : GetFunction no User Function defined using NULL to %p\n", This, pData);
(*(DWORD **) pData) = NULL;
} else {
if (This->baseShader.functionLength == 0) {
}
TRACE("(%p) : GetFunction copying to %p\n", This, pData);
memcpy(pData, This->baseShader.function, This->baseShader.functionLength);
}
return WINED3D_OK;
}
CONST SHADER_OPCODE IWineD3DPixelShaderImpl_shader_ins[] = {
/* Arithmethic */
{WINED3DSIO_NOP, "nop", "NOP", 0, 0, pshader_hw_map2gl, NULL, 0, 0},
{WINED3DSIO_MOV, "mov", "MOV", 1, 2, pshader_hw_map2gl, shader_glsl_mov, 0, 0},
{WINED3DSIO_ADD, "add", "ADD", 1, 3, pshader_hw_map2gl, shader_glsl_arith, 0, 0},
{WINED3DSIO_SUB, "sub", "SUB", 1, 3, pshader_hw_map2gl, shader_glsl_arith, 0, 0},
{WINED3DSIO_MAD, "mad", "MAD", 1, 4, pshader_hw_map2gl, shader_glsl_mad, 0, 0},
{WINED3DSIO_MUL, "mul", "MUL", 1, 3, pshader_hw_map2gl, shader_glsl_arith, 0, 0},
{WINED3DSIO_RCP, "rcp", "RCP", 1, 2, pshader_hw_map2gl, shader_glsl_rcp, 0, 0},
{WINED3DSIO_RSQ, "rsq", "RSQ", 1, 2, pshader_hw_map2gl, shader_glsl_rsq, 0, 0},
{WINED3DSIO_DP3, "dp3", "DP3", 1, 3, pshader_hw_map2gl, shader_glsl_dot, 0, 0},
{WINED3DSIO_DP4, "dp4", "DP4", 1, 3, pshader_hw_map2gl, shader_glsl_dot, 0, 0},
{WINED3DSIO_MIN, "min", "MIN", 1, 3, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
{WINED3DSIO_MAX, "max", "MAX", 1, 3, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
{WINED3DSIO_SLT, "slt", "SLT", 1, 3, pshader_hw_map2gl, shader_glsl_compare, 0, 0},
{WINED3DSIO_SGE, "sge", "SGE", 1, 3, pshader_hw_map2gl, shader_glsl_compare, 0, 0},
{WINED3DSIO_ABS, "abs", "ABS", 1, 2, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
{WINED3DSIO_EXP, "exp", "EX2", 1, 2, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
{WINED3DSIO_LOG, "log", "LG2", 1, 2, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
{WINED3DSIO_EXPP, "expp", "EXP", 1, 2, pshader_hw_map2gl, shader_glsl_expp, 0, 0},
{WINED3DSIO_LOGP, "logp", "LOG", 1, 2, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
{WINED3DSIO_DST, "dst", "DST", 1, 3, pshader_hw_map2gl, shader_glsl_dst, 0, 0},
{WINED3DSIO_LRP, "lrp", "LRP", 1, 4, pshader_hw_map2gl, shader_glsl_lrp, 0, 0},
{WINED3DSIO_FRC, "frc", "FRC", 1, 2, pshader_hw_map2gl, shader_glsl_map2gl, 0, 0},
{WINED3DSIO_CND, "cnd", NULL, 1, 4, pshader_hw_cnd, shader_glsl_cnd, WINED3DPS_VERSION(1,0), WINED3DPS_VERSION(1,4)},
{WINED3DSIO_CMP, "cmp", NULL, 1, 4, pshader_hw_cmp, shader_glsl_cmp, WINED3DPS_VERSION(1,2), WINED3DPS_VERSION(3,0)},
{WINED3DSIO_POW, "pow", "POW", 1, 3, NULL, shader_glsl_pow, 0, 0},
{WINED3DSIO_CRS, "crs", "XPS", 1, 3, NULL, shader_glsl_cross, 0, 0},
/* TODO: xyz normalise can be performed as VS_ARB using one temporary register,
DP3 tmp , vec, vec;
RSQ tmp, tmp.x;
MUL vec.xyz, vec, tmp;
but I think this is better because it accounts for w properly.
DP3 tmp , vec, vec;
RSQ tmp, tmp.x;
MUL vec, vec, tmp;
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -