| /* Direct3D Common functions |
| * Copyright (c) 1998 Lionel ULMER |
| * |
| * This file contains all common miscellaneous code that spans |
| * different 'objects' |
| * |
| * 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA |
| */ |
| |
| #include <stdarg.h> |
| |
| #define NONAMELESSUNION |
| #define NONAMELESSSTRUCT |
| #include "windef.h" |
| #include "winbase.h" |
| #include "objbase.h" |
| #include "wingdi.h" |
| #include "ddraw.h" |
| #include "d3d.h" |
| #include "wine/debug.h" |
| |
| #include "d3d_private.h" |
| |
| WINE_DEFAULT_DEBUG_CHANNEL(ddraw); |
| |
| const char *_get_renderstate(D3DRENDERSTATETYPE type) { |
| static const char * const states[] = { |
| "ERR", |
| "D3DRENDERSTATE_TEXTUREHANDLE", |
| "D3DRENDERSTATE_ANTIALIAS", |
| "D3DRENDERSTATE_TEXTUREADDRESS", |
| "D3DRENDERSTATE_TEXTUREPERSPECTIVE", |
| "D3DRENDERSTATE_WRAPU", |
| "D3DRENDERSTATE_WRAPV", |
| "D3DRENDERSTATE_ZENABLE", |
| "D3DRENDERSTATE_FILLMODE", |
| "D3DRENDERSTATE_SHADEMODE", |
| "D3DRENDERSTATE_LINEPATTERN", |
| "D3DRENDERSTATE_MONOENABLE", |
| "D3DRENDERSTATE_ROP2", |
| "D3DRENDERSTATE_PLANEMASK", |
| "D3DRENDERSTATE_ZWRITEENABLE", |
| "D3DRENDERSTATE_ALPHATESTENABLE", |
| "D3DRENDERSTATE_LASTPIXEL", |
| "D3DRENDERSTATE_TEXTUREMAG", |
| "D3DRENDERSTATE_TEXTUREMIN", |
| "D3DRENDERSTATE_SRCBLEND", |
| "D3DRENDERSTATE_DESTBLEND", |
| "D3DRENDERSTATE_TEXTUREMAPBLEND", |
| "D3DRENDERSTATE_CULLMODE", |
| "D3DRENDERSTATE_ZFUNC", |
| "D3DRENDERSTATE_ALPHAREF", |
| "D3DRENDERSTATE_ALPHAFUNC", |
| "D3DRENDERSTATE_DITHERENABLE", |
| "D3DRENDERSTATE_ALPHABLENDENABLE", |
| "D3DRENDERSTATE_FOGENABLE", |
| "D3DRENDERSTATE_SPECULARENABLE", |
| "D3DRENDERSTATE_ZVISIBLE", |
| "D3DRENDERSTATE_SUBPIXEL", |
| "D3DRENDERSTATE_SUBPIXELX", |
| "D3DRENDERSTATE_STIPPLEDALPHA", |
| "D3DRENDERSTATE_FOGCOLOR", |
| "D3DRENDERSTATE_FOGTABLEMODE", |
| "D3DRENDERSTATE_FOGTABLESTART", |
| "D3DRENDERSTATE_FOGTABLEEND", |
| "D3DRENDERSTATE_FOGTABLEDENSITY", |
| "D3DRENDERSTATE_STIPPLEENABLE", |
| "D3DRENDERSTATE_EDGEANTIALIAS", |
| "D3DRENDERSTATE_COLORKEYENABLE", |
| "ERR", |
| "D3DRENDERSTATE_BORDERCOLOR", |
| "D3DRENDERSTATE_TEXTUREADDRESSU", |
| "D3DRENDERSTATE_TEXTUREADDRESSV", |
| "D3DRENDERSTATE_MIPMAPLODBIAS", |
| "D3DRENDERSTATE_ZBIAS", |
| "D3DRENDERSTATE_RANGEFOGENABLE", |
| "D3DRENDERSTATE_ANISOTROPY", |
| "D3DRENDERSTATE_FLUSHBATCH", |
| "D3DRENDERSTATE_TRANSLUCENTSORTINDEPENDENT", |
| "D3DRENDERSTATE_STENCILENABLE", |
| "D3DRENDERSTATE_STENCILFAIL", |
| "D3DRENDERSTATE_STENCILZFAIL", |
| "D3DRENDERSTATE_STENCILPASS", |
| "D3DRENDERSTATE_STENCILFUNC", |
| "D3DRENDERSTATE_STENCILREF", |
| "D3DRENDERSTATE_STENCILMASK", |
| "D3DRENDERSTATE_STENCILWRITEMASK", |
| "D3DRENDERSTATE_TEXTUREFACTOR", |
| "ERR", |
| "ERR", |
| "ERR", |
| "D3DRENDERSTATE_STIPPLEPATTERN00", |
| "D3DRENDERSTATE_STIPPLEPATTERN01", |
| "D3DRENDERSTATE_STIPPLEPATTERN02", |
| "D3DRENDERSTATE_STIPPLEPATTERN03", |
| "D3DRENDERSTATE_STIPPLEPATTERN04", |
| "D3DRENDERSTATE_STIPPLEPATTERN05", |
| "D3DRENDERSTATE_STIPPLEPATTERN06", |
| "D3DRENDERSTATE_STIPPLEPATTERN07", |
| "D3DRENDERSTATE_STIPPLEPATTERN08", |
| "D3DRENDERSTATE_STIPPLEPATTERN09", |
| "D3DRENDERSTATE_STIPPLEPATTERN10", |
| "D3DRENDERSTATE_STIPPLEPATTERN11", |
| "D3DRENDERSTATE_STIPPLEPATTERN12", |
| "D3DRENDERSTATE_STIPPLEPATTERN13", |
| "D3DRENDERSTATE_STIPPLEPATTERN14", |
| "D3DRENDERSTATE_STIPPLEPATTERN15", |
| "D3DRENDERSTATE_STIPPLEPATTERN16", |
| "D3DRENDERSTATE_STIPPLEPATTERN17", |
| "D3DRENDERSTATE_STIPPLEPATTERN18", |
| "D3DRENDERSTATE_STIPPLEPATTERN19", |
| "D3DRENDERSTATE_STIPPLEPATTERN20", |
| "D3DRENDERSTATE_STIPPLEPATTERN21", |
| "D3DRENDERSTATE_STIPPLEPATTERN22", |
| "D3DRENDERSTATE_STIPPLEPATTERN23", |
| "D3DRENDERSTATE_STIPPLEPATTERN24", |
| "D3DRENDERSTATE_STIPPLEPATTERN25", |
| "D3DRENDERSTATE_STIPPLEPATTERN26", |
| "D3DRENDERSTATE_STIPPLEPATTERN27", |
| "D3DRENDERSTATE_STIPPLEPATTERN28", |
| "D3DRENDERSTATE_STIPPLEPATTERN29", |
| "D3DRENDERSTATE_STIPPLEPATTERN30", |
| "D3DRENDERSTATE_STIPPLEPATTERN31" |
| }; |
| static const char * const states_2[] = { |
| "D3DRENDERSTATE_WRAP0", |
| "D3DRENDERSTATE_WRAP1", |
| "D3DRENDERSTATE_WRAP2", |
| "D3DRENDERSTATE_WRAP3", |
| "D3DRENDERSTATE_WRAP4", |
| "D3DRENDERSTATE_WRAP5", |
| "D3DRENDERSTATE_WRAP6", |
| "D3DRENDERSTATE_WRAP7", |
| "D3DRENDERSTATE_CLIPPING", |
| "D3DRENDERSTATE_LIGHTING", |
| "D3DRENDERSTATE_EXTENTS", |
| "D3DRENDERSTATE_AMBIENT", |
| "D3DRENDERSTATE_FOGVERTEXMODE", |
| "D3DRENDERSTATE_COLORVERTEX", |
| "D3DRENDERSTATE_LOCALVIEWER", |
| "D3DRENDERSTATE_NORMALIZENORMALS", |
| "D3DRENDERSTATE_COLORKEYBLENDENABLE", |
| "D3DRENDERSTATE_DIFFUSEMATERIALSOURCE", |
| "D3DRENDERSTATE_SPECULARMATERIALSOURCE", |
| "D3DRENDERSTATE_AMBIENTMATERIALSOURCE", |
| "D3DRENDERSTATE_EMISSIVEMATERIALSOURCE", |
| "ERR", |
| "ERR", |
| "D3DRENDERSTATE_VERTEXBLEND", |
| "D3DRENDERSTATE_CLIPPLANEENABLE", |
| }; |
| if (type >= D3DRENDERSTATE_WRAP0) { |
| type -= D3DRENDERSTATE_WRAP0; |
| if (type >= (sizeof(states_2) / sizeof(states_2[0]))) return "ERR"; |
| return states_2[type]; |
| } |
| if (type >= (sizeof(states) / sizeof(states[0]))) return "ERR"; |
| return states[type]; |
| } |
| |
| void |
| dump_D3DCOLORVALUE(D3DCOLORVALUE *lpCol) |
| { |
| DPRINTF("%f %f %f %f", lpCol->u1.r, lpCol->u2.g, lpCol->u3.b, lpCol->u4.a); |
| } |
| |
| void |
| dump_D3DVECTOR(D3DVECTOR *lpVec) |
| { |
| DPRINTF("%f %f %f", lpVec->u1.x, lpVec->u2.y, lpVec->u3.z); |
| } |
| |
| void |
| dump_D3DMATERIAL7(LPD3DMATERIAL7 lpMat) |
| { |
| DPRINTF(" - diffuse : "); dump_D3DCOLORVALUE(&(lpMat->u.diffuse)); DPRINTF("\n"); |
| DPRINTF(" - ambient : "); dump_D3DCOLORVALUE(&(lpMat->u1.ambient)); DPRINTF("\n"); |
| DPRINTF(" - specular : "); dump_D3DCOLORVALUE(&(lpMat->u2.specular)); DPRINTF("\n"); |
| DPRINTF(" - emissive : "); dump_D3DCOLORVALUE(&(lpMat->u3.emissive)); DPRINTF("\n"); |
| DPRINTF(" - power : %f\n", lpMat->u4.power); |
| } |
| |
| void |
| dump_D3DLIGHT7(LPD3DLIGHT7 lpLight) |
| { |
| DPRINTF(" - light type : %s\n", (lpLight->dltType == D3DLIGHT_POINT ? "D3DLIGHT_POINT" : |
| (lpLight->dltType == D3DLIGHT_SPOT ? "D3DLIGHT_SPOT" : |
| (lpLight->dltType == D3DLIGHT_DIRECTIONAL ? "D3DLIGHT_DIRECTIONAL" : |
| "UNSUPPORTED")))); |
| DPRINTF(" - diffuse : "); dump_D3DCOLORVALUE(&(lpLight->dcvDiffuse)); DPRINTF("\n"); |
| DPRINTF(" - specular : "); dump_D3DCOLORVALUE(&(lpLight->dcvSpecular)); DPRINTF("\n"); |
| DPRINTF(" - ambient : "); dump_D3DCOLORVALUE(&(lpLight->dcvAmbient)); DPRINTF("\n"); |
| DPRINTF(" - position : "); dump_D3DVECTOR(&(lpLight->dvPosition)); DPRINTF("\n"); |
| DPRINTF(" - direction : "); dump_D3DVECTOR(&(lpLight->dvDirection)); DPRINTF("\n"); |
| DPRINTF(" - dvRange : %f\n", lpLight->dvRange); |
| DPRINTF(" - dvFalloff : %f\n", lpLight->dvFalloff); |
| DPRINTF(" - dvAttenuation : %f %f %f\n", lpLight->dvAttenuation0, lpLight->dvAttenuation1, lpLight->dvAttenuation2); |
| DPRINTF(" - dvTheta : %f\n", lpLight->dvTheta); |
| DPRINTF(" - dvPhi : %f\n", lpLight->dvPhi); |
| } |
| |
| void |
| dump_DPFLAGS(DWORD dwFlags) |
| { |
| static const flag_info flags[] = |
| { |
| FE(D3DDP_WAIT), |
| FE(D3DDP_OUTOFORDER), |
| FE(D3DDP_DONOTCLIP), |
| FE(D3DDP_DONOTUPDATEEXTENTS), |
| FE(D3DDP_DONOTLIGHT) |
| }; |
| |
| DDRAW_dump_flags(dwFlags, flags, sizeof(flags)/sizeof(flags[0])); |
| } |
| |
| void |
| dump_D3DMATRIX(D3DMATRIX *mat) |
| { |
| DPRINTF(" %f %f %f %f\n", mat->_11, mat->_12, mat->_13, mat->_14); |
| DPRINTF(" %f %f %f %f\n", mat->_21, mat->_22, mat->_23, mat->_24); |
| DPRINTF(" %f %f %f %f\n", mat->_31, mat->_32, mat->_33, mat->_34); |
| DPRINTF(" %f %f %f %f\n", mat->_41, mat->_42, mat->_43, mat->_44); |
| } |
| |
| |
| DWORD get_flexible_vertex_size(DWORD d3dvtVertexType) |
| { |
| DWORD size = 0; |
| |
| if (d3dvtVertexType & D3DFVF_NORMAL) size += 3 * sizeof(D3DVALUE); |
| if (d3dvtVertexType & D3DFVF_DIFFUSE) size += sizeof(DWORD); |
| if (d3dvtVertexType & D3DFVF_SPECULAR) size += sizeof(DWORD); |
| if (d3dvtVertexType & D3DFVF_RESERVED1) size += sizeof(DWORD); |
| switch (d3dvtVertexType & D3DFVF_POSITION_MASK) { |
| case D3DFVF_XYZ: size += 3 * sizeof(D3DVALUE); break; |
| case D3DFVF_XYZRHW: size += 4 * sizeof(D3DVALUE); break; |
| default: TRACE(" matrix weighting not handled yet...\n"); |
| } |
| size += 2 * sizeof(D3DVALUE) * ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); |
| |
| return size; |
| } |
| |
| void dump_flexible_vertex(DWORD d3dvtVertexType) |
| { |
| static const flag_info flags[] = { |
| FE(D3DFVF_NORMAL), |
| FE(D3DFVF_RESERVED1), |
| FE(D3DFVF_DIFFUSE), |
| FE(D3DFVF_SPECULAR) |
| }; |
| int i; |
| |
| if (d3dvtVertexType & D3DFVF_RESERVED0) DPRINTF("D3DFVF_RESERVED0 "); |
| switch (d3dvtVertexType & D3DFVF_POSITION_MASK) { |
| #define GEN_CASE(a) case a: DPRINTF(#a " "); break |
| GEN_CASE(D3DFVF_XYZ); |
| GEN_CASE(D3DFVF_XYZRHW); |
| GEN_CASE(D3DFVF_XYZB1); |
| GEN_CASE(D3DFVF_XYZB2); |
| GEN_CASE(D3DFVF_XYZB3); |
| GEN_CASE(D3DFVF_XYZB4); |
| GEN_CASE(D3DFVF_XYZB5); |
| } |
| DDRAW_dump_flags_(d3dvtVertexType, flags, sizeof(flags)/sizeof(flags[0]), FALSE); |
| switch (d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) { |
| GEN_CASE(D3DFVF_TEX0); |
| GEN_CASE(D3DFVF_TEX1); |
| GEN_CASE(D3DFVF_TEX2); |
| GEN_CASE(D3DFVF_TEX3); |
| GEN_CASE(D3DFVF_TEX4); |
| GEN_CASE(D3DFVF_TEX5); |
| GEN_CASE(D3DFVF_TEX6); |
| GEN_CASE(D3DFVF_TEX7); |
| GEN_CASE(D3DFVF_TEX8); |
| } |
| #undef GEN_CASE |
| for (i = 0; i < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); i++) { |
| DPRINTF(" T%d-s%ld", i + 1, (((d3dvtVertexType >> (16 + (2 * i))) + 1) & 0x03) + 1); |
| } |
| DPRINTF("\n"); |
| } |
| |
| void |
| convert_FVF_to_strided_data(DWORD d3dvtVertexType, LPVOID lpvVertices, D3DDRAWPRIMITIVESTRIDEDDATA *strided, DWORD dwStartVertex) |
| { |
| int current_offset = 0; |
| int tex_index; |
| int size = get_flexible_vertex_size(d3dvtVertexType); |
| |
| lpvVertices = ((BYTE *) lpvVertices) + (size * dwStartVertex); |
| |
| if ((d3dvtVertexType & D3DFVF_POSITION_MASK) == D3DFVF_XYZ) { |
| strided->position.lpvData = lpvVertices; |
| current_offset += 3 * sizeof(D3DVALUE); |
| } else { |
| strided->position.lpvData = lpvVertices; |
| current_offset += 4 * sizeof(D3DVALUE); |
| } |
| if (d3dvtVertexType & D3DFVF_RESERVED1) { |
| current_offset += sizeof(DWORD); |
| } |
| if (d3dvtVertexType & D3DFVF_NORMAL) { |
| strided->normal.lpvData = ((char *) lpvVertices) + current_offset; |
| current_offset += 3 * sizeof(D3DVALUE); |
| } |
| if (d3dvtVertexType & D3DFVF_DIFFUSE) { |
| strided->diffuse.lpvData = ((char *) lpvVertices) + current_offset; |
| current_offset += sizeof(DWORD); |
| } |
| if (d3dvtVertexType & D3DFVF_SPECULAR) { |
| strided->specular.lpvData = ((char *) lpvVertices) + current_offset; |
| current_offset += sizeof(DWORD); |
| } |
| for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) { |
| strided->textureCoords[tex_index].lpvData = ((char *) lpvVertices) + current_offset; |
| current_offset += 2 * sizeof(D3DVALUE); |
| } |
| strided->position.dwStride = current_offset; |
| strided->normal.dwStride = current_offset; |
| strided->diffuse.dwStride = current_offset; |
| strided->specular.dwStride = current_offset; |
| for (tex_index = 0; tex_index < ((d3dvtVertexType & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT); tex_index++) |
| strided->textureCoords[tex_index].dwStride = current_offset; |
| } |
| |
| void |
| dump_D3DVOP(DWORD dwVertexOp) |
| { |
| static const flag_info flags[] = |
| { |
| FE(D3DVOP_LIGHT), |
| FE(D3DVOP_CLIP), |
| FE(D3DVOP_EXTENTS), |
| FE(D3DVOP_TRANSFORM) |
| }; |
| DDRAW_dump_flags(dwVertexOp, flags, sizeof(flags)/sizeof(flags[0])); |
| } |
| |
| void |
| dump_D3DPV(DWORD dwFlags) |
| { |
| if (dwFlags == D3DPV_DONOTCOPYDATA) DPRINTF("D3DPV_DONOTCOPYDATA\n"); |
| else if (dwFlags != 0) DPRINTF("Unknown !!!\n"); |
| else DPRINTF("\n"); |
| } |
| |
| void multiply_matrix(LPD3DMATRIX dest, LPD3DMATRIX src1, LPD3DMATRIX src2) |
| { |
| D3DMATRIX temp; |
| |
| /* Now do the multiplication 'by hand'. |
| I know that all this could be optimised, but this will be done later :-) */ |
| temp._11 = (src1->_11 * src2->_11) + (src1->_21 * src2->_12) + (src1->_31 * src2->_13) + (src1->_41 * src2->_14); |
| temp._21 = (src1->_11 * src2->_21) + (src1->_21 * src2->_22) + (src1->_31 * src2->_23) + (src1->_41 * src2->_24); |
| temp._31 = (src1->_11 * src2->_31) + (src1->_21 * src2->_32) + (src1->_31 * src2->_33) + (src1->_41 * src2->_34); |
| temp._41 = (src1->_11 * src2->_41) + (src1->_21 * src2->_42) + (src1->_31 * src2->_43) + (src1->_41 * src2->_44); |
| |
| temp._12 = (src1->_12 * src2->_11) + (src1->_22 * src2->_12) + (src1->_32 * src2->_13) + (src1->_42 * src2->_14); |
| temp._22 = (src1->_12 * src2->_21) + (src1->_22 * src2->_22) + (src1->_32 * src2->_23) + (src1->_42 * src2->_24); |
| temp._32 = (src1->_12 * src2->_31) + (src1->_22 * src2->_32) + (src1->_32 * src2->_33) + (src1->_42 * src2->_34); |
| temp._42 = (src1->_12 * src2->_41) + (src1->_22 * src2->_42) + (src1->_32 * src2->_43) + (src1->_42 * src2->_44); |
| |
| temp._13 = (src1->_13 * src2->_11) + (src1->_23 * src2->_12) + (src1->_33 * src2->_13) + (src1->_43 * src2->_14); |
| temp._23 = (src1->_13 * src2->_21) + (src1->_23 * src2->_22) + (src1->_33 * src2->_23) + (src1->_43 * src2->_24); |
| temp._33 = (src1->_13 * src2->_31) + (src1->_23 * src2->_32) + (src1->_33 * src2->_33) + (src1->_43 * src2->_34); |
| temp._43 = (src1->_13 * src2->_41) + (src1->_23 * src2->_42) + (src1->_33 * src2->_43) + (src1->_43 * src2->_44); |
| |
| temp._14 = (src1->_14 * src2->_11) + (src1->_24 * src2->_12) + (src1->_34 * src2->_13) + (src1->_44 * src2->_14); |
| temp._24 = (src1->_14 * src2->_21) + (src1->_24 * src2->_22) + (src1->_34 * src2->_23) + (src1->_44 * src2->_24); |
| temp._34 = (src1->_14 * src2->_31) + (src1->_24 * src2->_32) + (src1->_34 * src2->_33) + (src1->_44 * src2->_34); |
| temp._44 = (src1->_14 * src2->_41) + (src1->_24 * src2->_42) + (src1->_34 * src2->_43) + (src1->_44 * src2->_44); |
| |
| /* And copy the new matrix in the good storage.. */ |
| memcpy(dest, &temp, 16 * sizeof(D3DVALUE)); |
| } |