Index: ddraw/glDirect3DDevice.cpp |
— | — | @@ -210,16 +210,14 @@ |
211 | 211 | diffuse = specular = NULL;
|
212 | 212 | ZeroMemory(texcoords,8*sizeof(GLfloat*));
|
213 | 213 | memcpy(renderstate,renderstate_default,153*sizeof(DWORD));
|
214 | | - __gluMakeIdentityf(matWorld);
|
215 | | - __gluMakeIdentityf(matView);
|
216 | | - __gluMakeIdentityf(matProjection);
|
217 | | - __gluMakeIdentityf(matNormal);
|
| 214 | + __gluMakeIdentityf((GLfloat*)&matrices[0]);
|
| 215 | + for(int i = 1; i < 24; i++)
|
| 216 | + memcpy(&matrices[i],&matrices[0],sizeof(D3DMATRIX));
|
218 | 217 | texstages[0] = texstagedefault0;
|
219 | 218 | texstages[1] = texstages[2] = texstages[3] = texstages[4] =
|
220 | 219 | texstages[5] = texstages[6] = texstages[7] = texstagedefault1;
|
221 | 220 | refcount = 1;
|
222 | 221 | inscene = false;
|
223 | | - normal_dirty = false;
|
224 | 222 | this->glD3D7 = glD3D7;
|
225 | 223 | glD3D7->AddRef();
|
226 | 224 | this->glDDS7 = glDDS7;
|
— | — | @@ -235,6 +233,8 @@ |
236 | 234 | d3ddesc.dwMaxTextureWidth = d3ddesc.dwMaxTextureHeight =
|
237 | 235 | d3ddesc.dwMaxTextureRepeat = d3ddesc.dwMaxTextureAspectRatio = glD3D7->glDD7->renderer->gl_caps.TextureMax;
|
238 | 236 | glD3D7->glDD7->renderer->InitD3D(zbuffer);
|
| 237 | + glD3D7->glDD7->renderer->SetRenderState(0,153,renderstate);
|
| 238 | + glD3D7->glDD7->renderer->SetMatrix(0,24,matrices);
|
239 | 239 | }
|
240 | 240 | glDirect3DDevice7::~glDirect3DDevice7()
|
241 | 241 | {
|
— | — | @@ -513,8 +513,8 @@ |
514 | 514 | if(!inscene) return D3DERR_SCENE_NOT_IN_SCENE;
|
515 | 515 | HRESULT err = fvftoglvertex(dwVertexTypeDesc,(LPDWORD)lpvVertices);
|
516 | 516 | if(err != D3D_OK) return err;
|
517 | | - return glD3D7->glDD7->renderer->DrawPrimitives(this,setdrawmode(d3dptPrimitiveType),vertdata,texformats,
|
518 | | - dwVertexCount,lpwIndices,dwIndexCount,dwFlags);
|
| 517 | + return glD3D7->glDD7->renderer->DrawPrimitives(this,setdrawmode(d3dptPrimitiveType),
|
| 518 | + vertdata,true,texformats,dwVertexCount,lpwIndices,dwIndexCount,dwFlags);
|
519 | 519 | }
|
520 | 520 | HRESULT WINAPI glDirect3DDevice7::DrawIndexedPrimitiveStrided(D3DPRIMITIVETYPE d3dptPrimitiveType, DWORD dwVertexTypeDesc,
|
521 | 521 | LPD3DDRAWPRIMITIVESTRIDEDDATA lpvVerticexArray, DWORD dwVertexCount, LPWORD lpwIndices, DWORD dwIndexCount, DWORD dwFlags)
|
— | — | @@ -772,20 +772,9 @@ |
773 | 773 | HRESULT WINAPI glDirect3DDevice7::GetTransform(D3DTRANSFORMSTATETYPE dtstTransformStateType, LPD3DMATRIX lpD3DMatrix)
|
774 | 774 | {
|
775 | 775 | if(!this) return DDERR_INVALIDPARAMS;
|
776 | | - switch(dtstTransformStateType)
|
777 | | - {
|
778 | | - case D3DTRANSFORMSTATE_WORLD:
|
779 | | - memcpy(lpD3DMatrix,&matWorld,sizeof(D3DMATRIX));
|
780 | | - return D3D_OK;
|
781 | | - case D3DTRANSFORMSTATE_VIEW:
|
782 | | - memcpy(lpD3DMatrix,&matView,sizeof(D3DMATRIX));
|
783 | | - return D3D_OK;
|
784 | | - case D3DTRANSFORMSTATE_PROJECTION:
|
785 | | - memcpy(lpD3DMatrix,&matProjection,sizeof(D3DMATRIX));
|
786 | | - return D3D_OK;
|
787 | | - default:
|
788 | | - ERR(DDERR_INVALIDPARAMS);
|
789 | | - }
|
| 776 | + if(dtstTransformStateType > D3DTRANSFORMSTATE_TEXTURE7) return DDERR_INVALIDPARAMS;
|
| 777 | + memcpy(lpD3DMatrix,&matrices[dtstTransformStateType],sizeof(D3DMATRIX));
|
| 778 | + return D3D_OK;
|
790 | 779 | }
|
791 | 780 | HRESULT WINAPI glDirect3DDevice7::GetViewport(LPD3DVIEWPORT7 lpViewport)
|
792 | 781 | {
|
— | — | @@ -1138,22 +1127,10 @@ |
1139 | 1128 | HRESULT WINAPI glDirect3DDevice7::SetTransform(D3DTRANSFORMSTATETYPE dtstTransformStateType, LPD3DMATRIX lpD3DMatrix)
|
1140 | 1129 | {
|
1141 | 1130 | if(!this) return DDERR_INVALIDPARAMS;
|
1142 | | - switch(dtstTransformStateType)
|
1143 | | - {
|
1144 | | - case D3DTRANSFORMSTATE_WORLD:
|
1145 | | - memcpy(&matWorld,lpD3DMatrix,sizeof(D3DMATRIX));
|
1146 | | - normal_dirty = true;
|
1147 | | - return D3D_OK;
|
1148 | | - case D3DTRANSFORMSTATE_VIEW:
|
1149 | | - memcpy(&matView,lpD3DMatrix,sizeof(D3DMATRIX));
|
1150 | | - normal_dirty = true;
|
1151 | | - return D3D_OK;
|
1152 | | - case D3DTRANSFORMSTATE_PROJECTION:
|
1153 | | - memcpy(&matProjection,lpD3DMatrix,sizeof(D3DMATRIX));
|
1154 | | - return D3D_OK;
|
1155 | | - default:
|
1156 | | - ERR(DDERR_INVALIDPARAMS);
|
1157 | | - }
|
| 1131 | + if(dtstTransformStateType > D3DTRANSFORMSTATE_TEXTURE7) return DDERR_INVALIDPARAMS;
|
| 1132 | + memcpy(&matrices[dtstTransformStateType],lpD3DMatrix,sizeof(D3DMATRIX));
|
| 1133 | + glD3D7->glDD7->renderer->SetMatrix(dtstTransformStateType,1,lpD3DMatrix);
|
| 1134 | + return D3D_OK;
|
1158 | 1135 | }
|
1159 | 1136 | HRESULT WINAPI glDirect3DDevice7::SetViewport(LPD3DVIEWPORT7 lpViewport)
|
1160 | 1137 | {
|
— | — | @@ -1187,26 +1164,3 @@ |
1188 | 1165 | return D3D_OK;
|
1189 | 1166 | }
|
1190 | 1167 |
|
1191 | | -void glDirect3DDevice7::UpdateNormalMatrix()
|
1192 | | -{
|
1193 | | - GLfloat worldview[16];
|
1194 | | - GLfloat tmp[16];
|
1195 | | -
|
1196 | | - ZeroMemory(&worldview,sizeof(D3DMATRIX));
|
1197 | | - ZeroMemory(&tmp,sizeof(D3DMATRIX));
|
1198 | | - __gluMultMatricesf(matWorld,matView,worldview); // Get worldview
|
1199 | | - if(__gluInvertMatrixf(worldview,tmp)) // Invert
|
1200 | | - {
|
1201 | | - memcpy(matNormal,tmp,3*sizeof(GLfloat));
|
1202 | | - memcpy(matNormal+3,tmp+4,3*sizeof(GLfloat));
|
1203 | | - memcpy(matNormal+6,tmp+8,3*sizeof(GLfloat));
|
1204 | | - }
|
1205 | | - else
|
1206 | | - {
|
1207 | | - memcpy(matNormal,worldview,3*sizeof(GLfloat));
|
1208 | | - memcpy(matNormal+3,worldview+4,3*sizeof(GLfloat));
|
1209 | | - memcpy(matNormal+6,worldview+8,3*sizeof(GLfloat));
|
1210 | | - }
|
1211 | | -
|
1212 | | - normal_dirty = false;
|
1213 | | -} |
\ No newline at end of file |
Index: ddraw/glDirect3DDevice.h |
— | — | @@ -122,12 +122,7 @@ |
123 | 123 | HRESULT WINAPI ValidateDevice(LPDWORD lpdwPasses);
|
124 | 124 | void SetArraySize(DWORD size, DWORD vertex, DWORD texcoord);
|
125 | 125 | __int64 SelectShader(GLVERTEX *VertexType);
|
126 | | - void UpdateNormalMatrix();
|
127 | | - GLfloat matWorld[16];
|
128 | | - GLfloat matView[16];
|
129 | | - GLfloat matProjection[16];
|
130 | | - GLfloat matNormal[9];
|
131 | | - bool normal_dirty;
|
| 126 | + D3DMATRIX matrices[24];
|
132 | 127 | D3DMATERIAL7 material;
|
133 | 128 | D3DVIEWPORT7 viewport;
|
134 | 129 | glDirect3DLight **lights;
|
— | — | @@ -153,7 +148,7 @@ |
154 | 149 | GLubyte *ambient;
|
155 | 150 | GLfloat *texcoords[8];
|
156 | 151 | GLVERTEX vertdata[18];
|
157 | | - int texformats[8];
|
| 152 | + DWORD texformats[8];
|
158 | 153 | };
|
159 | 154 |
|
160 | 155 | #endif //__GLDIRECT3DDEVICE_H |
\ No newline at end of file |
Index: ddraw/glDirectDraw.cpp |
— | — | @@ -1380,7 +1380,7 @@ |
1381 | 1381 |
|
1382 | 1382 | void glDirectDraw7::DeleteGL()
|
1383 | 1383 | {
|
1384 | | - delete renderer;
|
| 1384 | + if(renderer) delete renderer;
|
1385 | 1385 | renderer = NULL;
|
1386 | 1386 | }
|
1387 | 1387 |
|
Index: ddraw/glRenderer.cpp |
— | — | @@ -15,6 +15,11 @@ |
16 | 16 | // License along with this library; if not, write to the Free Software
|
17 | 17 | // Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
|
18 | 18 |
|
| 19 | +/**
|
| 20 | + * @file glRenderer.cpp
|
| 21 | + * @brief Contains the functions that control the DXGL rendering pipeline.
|
| 22 | + */
|
| 23 | +
|
19 | 24 | #include "common.h"
|
20 | 25 | #include "glDirectDraw.h"
|
21 | 26 | #include "glDirectDrawSurface.h"
|
— | — | @@ -26,6 +31,7 @@ |
27 | 32 | #include "ddraw.h"
|
28 | 33 | #include "scalers.h"
|
29 | 34 | #include <string>
|
| 35 | +#include <cstdarg>
|
30 | 36 | using namespace std;
|
31 | 37 | #include "shadergen.h"
|
32 | 38 | #include "matrix.h"
|
— | — | @@ -37,12 +43,55 @@ |
38 | 44 | int backy = 0;
|
39 | 45 | BltVertex bltvertices[4];
|
40 | 46 | const GLushort bltindices[4] = {0,1,2,3};
|
| 47 | +const RECT nullrect = {0,0,0,0};
|
41 | 48 |
|
| 49 | +/**
|
| 50 | + * Waits for an object to be signaled, while processing window messages received
|
| 51 | + * by the calling thread.
|
| 52 | + * @param object
|
| 53 | + * Win32 handle to the object to wait for
|
| 54 | + */
|
| 55 | +void WaitForMessageAndObject(HANDLE object)
|
| 56 | +{
|
| 57 | + bool loop = true;
|
| 58 | + DWORD wake;
|
| 59 | + MSG msg;
|
| 60 | + DWORD error;
|
| 61 | + while(loop)
|
| 62 | + {
|
| 63 | + wake = MsgWaitForMultipleObjects(1,&object,FALSE,INFINITE,QS_ALLEVENTS);
|
| 64 | + if(wake == (WAIT_OBJECT_0+1))
|
| 65 | + {
|
| 66 | + while(PeekMessage(&msg,NULL,0,0,PM_REMOVE))
|
| 67 | + {
|
| 68 | + TranslateMessage(&msg);
|
| 69 | + DispatchMessage(&msg);
|
| 70 | + }
|
| 71 | + }
|
| 72 | + else loop = false;
|
| 73 | + error = GetLastError();
|
| 74 | + }
|
| 75 | +}
|
42 | 76 |
|
| 77 | +/**
|
| 78 | + * Expands a 5-bit value to 8 bits.
|
| 79 | + * @param number
|
| 80 | + * 5-bit value to convert to 8 bits.
|
| 81 | + * @return
|
| 82 | + * Converted 8-bit value
|
| 83 | + */
|
43 | 84 | inline int _5to8bit(int number)
|
44 | 85 | {
|
45 | 86 | return (number << 3)+(number>>2);
|
46 | 87 | }
|
| 88 | +
|
| 89 | +/**
|
| 90 | + * Expands a 6-bit value to 8 bits.
|
| 91 | + * @param number
|
| 92 | + * 6-bit value to convert to 8 bits.
|
| 93 | + * @return
|
| 94 | + * Converted 8-bit value
|
| 95 | + */
|
47 | 96 | inline int _6to8bit(int number)
|
48 | 97 | {
|
49 | 98 | return (number<<2)+(number>>4);
|
— | — | @@ -50,6 +99,12 @@ |
51 | 100 |
|
52 | 101 | int oldswap = 0;
|
53 | 102 | int swapinterval = 0;
|
| 103 | +
|
| 104 | +/**
|
| 105 | + * Sets the Windows OpenGL swap interval
|
| 106 | + * @param swap
|
| 107 | + * Number of vertical retraces to wait per frame, 0 disable vsync
|
| 108 | + */
|
54 | 109 | inline void SetSwap(int swap)
|
55 | 110 | {
|
56 | 111 | if(swap != oldswap)
|
— | — | @@ -60,8 +115,151 @@ |
61 | 116 | }
|
62 | 117 | }
|
63 | 118 |
|
64 | | -int glRenderer::_UploadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2, int texformat3)
|
| 119 | +/**
|
| 120 | + * Adds a command to the renderer queue.\n
|
| 121 | + * If the command requires more space than the queue buffer, the buffer will be
|
| 122 | + * expanded. If there is no free space for the command, execution will pause
|
| 123 | + * until the queue has been sufficiently emptied.
|
| 124 | + * @param opcode
|
| 125 | + * Code that describes the command to be added to the queue.
|
| 126 | + * @param mode
|
| 127 | + * Method to use for synchronization:
|
| 128 | + * - 0: Do not fail the call
|
| 129 | + * - 1: Fail if queue is full
|
| 130 | + * - 2: Fail if queue is not empty
|
| 131 | + * @param size
|
| 132 | + * Size of the command in DWORDs
|
| 133 | + * @param paramcount
|
| 134 | + * Number of parameters to add to the queue command.
|
| 135 | + * @param ...
|
| 136 | + * Parameters for the command, when required. This is given in pairs of two
|
| 137 | + * arguments:
|
| 138 | + * - size: The size of the parameter, in bytes. Note that parameters are DWORD
|
| 139 | + * aligned. The size cannot exceed the size of the command, minus data already
|
| 140 | + * written to the queue.
|
| 141 | + * - pointer: A pointer to the data to be added to the command.\n
|
| 142 | + * If no parameters are used for the opcode, then supply 0 and NULL for the ...
|
| 143 | + * parameter.
|
| 144 | + * @return
|
| 145 | + * Zero if the call succeeds, nonzero otherwise.
|
| 146 | + */
|
| 147 | +int glRenderer::AddQueue(DWORD opcode, int mode, DWORD size, int paramcount, ...)
|
65 | 148 | {
|
| 149 | + EnterCriticalSection(&queuecs);
|
| 150 | + if((mode == 2) && queuelength)
|
| 151 | + {
|
| 152 | + LeaveCriticalSection(&queuecs);
|
| 153 | + return 1;
|
| 154 | + }
|
| 155 | + va_list params;
|
| 156 | + // Check queue size
|
| 157 | + va_start(params,paramcount);
|
| 158 | + int argsize;
|
| 159 | + void *argptr;
|
| 160 | + if(size > queuesize)
|
| 161 | + {
|
| 162 | + queue = (LPDWORD)realloc(queue,(queuesize+size)*sizeof(DWORD));
|
| 163 | + queuesize += size;
|
| 164 | + }
|
| 165 | + if(queuesize - queue_write < size)
|
| 166 | + {
|
| 167 | + if(queue_read < size)
|
| 168 | + {
|
| 169 | + if(mode == 1)
|
| 170 | + {
|
| 171 | + LeaveCriticalSection(&queuecs);
|
| 172 | + return 1;
|
| 173 | + }
|
| 174 | + if(queue_write < queuesize)
|
| 175 | + {
|
| 176 | + queue[queue_write] = OP_RESETQUEUE;
|
| 177 | + queuelength++;
|
| 178 | + }
|
| 179 | + LeaveCriticalSection(&queuecs);
|
| 180 | + Sync(size);
|
| 181 | + EnterCriticalSection(&queuecs);
|
| 182 | + }
|
| 183 | + }
|
| 184 | + if(queue_write < queue_read)
|
| 185 | + {
|
| 186 | + if(queue_read - queue_write < size)
|
| 187 | + {
|
| 188 | + LeaveCriticalSection(&queuecs);
|
| 189 | + Sync(size);
|
| 190 | + EnterCriticalSection(&queuecs);
|
| 191 | + }
|
| 192 | + }
|
| 193 | + queue[queue_write++] = opcode;
|
| 194 | + queue[queue_write++] = size;
|
| 195 | + size -= 2;
|
| 196 | + for(int i = 0; i < paramcount; i++)
|
| 197 | + {
|
| 198 | + argsize = va_arg(params,int);
|
| 199 | + argptr = va_arg(params,void*);
|
| 200 | + if(!argsize) continue;
|
| 201 | + if((NextMultipleOf4(argsize)/4) > size) break;
|
| 202 | + queue[queue_write++] = argsize;
|
| 203 | + if(argptr) memcpy(queue+queue_write,argptr,argsize);
|
| 204 | + queue_write += (NextMultipleOf4(argsize)/4);
|
| 205 | + size -= (NextMultipleOf4(argsize)/4);
|
| 206 | + }
|
| 207 | + va_end(params);
|
| 208 | + queuelength++;
|
| 209 | + if(!running) SetEvent(start);
|
| 210 | + LeaveCriticalSection(&queuecs);
|
| 211 | + return 0;
|
| 212 | +}
|
| 213 | +
|
| 214 | +/**
|
| 215 | + * Waits until the specified amount of queue space is free
|
| 216 | + * @param size
|
| 217 | + * If nonzero, the number of DWORDs that must be available within the queue.
|
| 218 | + * If zero, waits until the queue is empty.
|
| 219 | + */
|
| 220 | +void glRenderer::Sync(int size)
|
| 221 | +{
|
| 222 | + EnterCriticalSection(&queuecs);
|
| 223 | + if(!queuelength && !running)
|
| 224 | + {
|
| 225 | + LeaveCriticalSection(&queuecs);
|
| 226 | + return;
|
| 227 | + }
|
| 228 | + ResetEvent(sync);
|
| 229 | + syncsize = size;
|
| 230 | + if(!running) SetEvent(start);
|
| 231 | + LeaveCriticalSection(&queuecs);
|
| 232 | + WaitForMessageAndObject(sync);
|
| 233 | +}
|
| 234 | +
|
| 235 | +/**
|
| 236 | + * Internal function for uploading surface content to an OpenGL texture
|
| 237 | + * @param buffer
|
| 238 | + * Contains the contents of the surface
|
| 239 | + * @param bigbuffer
|
| 240 | + * Optional buffer to receive the rescaled surface contents, for when primary
|
| 241 | + * scaling is enabled.
|
| 242 | + * @param texture
|
| 243 | + * OpenGL texture name to upload to
|
| 244 | + * @param x,y
|
| 245 | + * Width and height of the surface
|
| 246 | + * @param bigx,bigy
|
| 247 | + * Width and height of the scaled surface buffer
|
| 248 | + * @param pitch
|
| 249 | + * Bytes from one line of graphics to the next in the surface
|
| 250 | + * @param bigpitch
|
| 251 | + * Pitch of the scaled surface buffer
|
| 252 | + * @param bpp
|
| 253 | + * Number of bits per surface pixel
|
| 254 | + * @param texformat
|
| 255 | + * OpenGL format parameter for glTexImage2D
|
| 256 | + * @param texformat2
|
| 257 | + * OpenGL type parameter for glTexImage2D
|
| 258 | + * @param texformat3
|
| 259 | + * OpenGL internalformat parameter for glTexImage2D
|
| 260 | + */
|
| 261 | +void glRenderer::_UploadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y,
|
| 262 | + int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2, int texformat3)
|
| 263 | +{
|
66 | 264 | if(bpp == 15) bpp = 16;
|
67 | 265 | glBindTexture(GL_TEXTURE_2D,texture); // Select surface's texture
|
68 | 266 | if((x == bigx && y == bigy) || !bigbuffer)
|
— | — | @@ -88,9 +286,35 @@ |
89 | 287 | }
|
90 | 288 | glTexImage2D(GL_TEXTURE_2D,0,texformat3,bigx,bigy,0,texformat,texformat2,bigbuffer);
|
91 | 289 | }
|
92 | | - return 0;
|
93 | 290 | }
|
94 | | -int glRenderer::_DownloadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2)
|
| 291 | +
|
| 292 | +
|
| 293 | +/**
|
| 294 | + * Internal function for downloading surface content from an OpenGL texture
|
| 295 | + * @param buffer
|
| 296 | + * Buffer to receive the surface contents
|
| 297 | + * @param bigbuffer
|
| 298 | + * Optional buffer to receive the rescaled surface contents, for when primary
|
| 299 | + * scaling is enabled.
|
| 300 | + * @param texture
|
| 301 | + * OpenGL texture name to download from
|
| 302 | + * @param x,y
|
| 303 | + * Width and height of the surface
|
| 304 | + * @param bigx,bigy
|
| 305 | + * Width and height of the scaled surface buffer
|
| 306 | + * @param pitch
|
| 307 | + * Bytes from one line of graphics to the next in the surface
|
| 308 | + * @param bigpitch
|
| 309 | + * Pitch of the scaled surface buffer
|
| 310 | + * @param bpp
|
| 311 | + * Number of bits per surface pixel
|
| 312 | + * @param texformat
|
| 313 | + * OpenGL format parameter for glGetTexImage
|
| 314 | + * @param texformat2
|
| 315 | + * OpenGL type parameter for glGetTexImage
|
| 316 | + */
|
| 317 | +void glRenderer::_DownloadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y,
|
| 318 | + int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2)
|
95 | 319 | {
|
96 | 320 | glBindTexture(GL_TEXTURE_2D,texture); // Select surface's texture
|
97 | 321 | if((bigx == x && bigy == y) || !bigbuffer)
|
— | — | @@ -118,21 +342,34 @@ |
119 | 343 | break;
|
120 | 344 | }
|
121 | 345 | }
|
122 | | - return 0;
|
123 | 346 | }
|
124 | 347 |
|
| 348 | +/**
|
| 349 | + * Constructor for the glRenderer object
|
| 350 | + * @param width,height,bpp
|
| 351 | + * Width, height, and BPP of the rendering window
|
| 352 | + * @param fullscreen
|
| 353 | + * True if fullscreen mode is required, false for windowed
|
| 354 | + * @param hwnd
|
| 355 | + * Handle of the window to render into. If this value is NULL, then a transparent
|
| 356 | + * layered window will be created for the renderer.
|
| 357 | + * @param glDD7
|
| 358 | + * Pointer to the glDirectDraw7 object that is managing the glRenderer object
|
| 359 | + */
|
125 | 360 | glRenderer::glRenderer(int width, int height, int bpp, bool fullscreen, HWND hwnd, glDirectDraw7 *glDD7)
|
126 | 361 | {
|
127 | | - MSG Msg;
|
128 | | - wndbusy = false;
|
129 | 362 | hDC = NULL;
|
130 | 363 | hRC = NULL;
|
131 | 364 | PBO = 0;
|
132 | 365 | hasHWnd = false;
|
133 | 366 | dib.enabled = false;
|
| 367 | + normal_dirty = false;
|
| 368 | + running = false;
|
134 | 369 | hWnd = hwnd;
|
135 | 370 | hRenderWnd = NULL;
|
136 | | - InitializeCriticalSection(&cs);
|
| 371 | + busy = CreateEvent(NULL,FALSE,FALSE,NULL);
|
| 372 | + InitializeCriticalSection(&commandcs);
|
| 373 | + InitializeCriticalSection(&queuecs);
|
137 | 374 | if(fullscreen)
|
138 | 375 | {
|
139 | 376 | SetWindowLongPtrA(hWnd,GWL_EXSTYLE,WS_EX_APPWINDOW);
|
— | — | @@ -143,6 +380,7 @@ |
144 | 381 | {
|
145 | 382 | // TODO: Adjust window rect
|
146 | 383 | }
|
| 384 | + EnterCriticalSection(&commandcs);
|
147 | 385 | SetWindowPos(hWnd,HWND_TOP,0,0,0,0,SWP_NOMOVE | SWP_NOSIZE | SWP_FRAMECHANGED);
|
148 | 386 | inputs[0] = (void*)width;
|
149 | 387 | inputs[1] = (void*)height;
|
— | — | @@ -151,39 +389,31 @@ |
152 | 390 | inputs[4] = (void*)hWnd;
|
153 | 391 | inputs[5] = glDD7;
|
154 | 392 | inputs[6] = this;
|
155 | | - wndbusy = true;
|
156 | 393 | hThread = CreateThread(NULL,0,ThreadEntry,inputs,0,NULL);
|
157 | | - while(wndbusy)
|
158 | | - {
|
159 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
160 | | - {
|
161 | | - TranslateMessage(&Msg);
|
162 | | - DispatchMessage(&Msg);
|
163 | | - }
|
164 | | - Sleep(0);
|
165 | | - }
|
| 394 | + WaitForMessageAndObject(busy);
|
| 395 | + LeaveCriticalSection(&commandcs);
|
166 | 396 | }
|
167 | 397 |
|
| 398 | +/**
|
| 399 | + * Destructor for the glRenderer object
|
| 400 | + */
|
168 | 401 | glRenderer::~glRenderer()
|
169 | 402 | {
|
170 | | - MSG Msg;
|
171 | | - EnterCriticalSection(&cs);
|
172 | | - wndbusy = true;
|
173 | | - SendMessage(hRenderWnd,GLEVENT_DELETE,0,0);
|
174 | | - while(wndbusy)
|
175 | | - {
|
176 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
177 | | - {
|
178 | | - TranslateMessage(&Msg);
|
179 | | - DispatchMessage(&Msg);
|
180 | | - }
|
181 | | - Sleep(0);
|
182 | | - }
|
183 | | - LeaveCriticalSection(&cs);
|
184 | | - DeleteCriticalSection(&cs);
|
| 403 | + EnterCriticalSection(&commandcs);
|
| 404 | + AddQueue(OP_DELETE,0,2,0,NULL);
|
| 405 | + Sync(0);
|
| 406 | + LeaveCriticalSection(&commandcs);
|
| 407 | + DeleteCriticalSection(&commandcs);
|
| 408 | + CloseHandle(busy);
|
| 409 | + CloseHandle(sync);
|
| 410 | + CloseHandle(start);
|
185 | 411 | }
|
186 | 412 |
|
187 | | -
|
| 413 | +/**
|
| 414 | + * Entry point for the renderer thread
|
| 415 | + * @param entry
|
| 416 | + * Pointer to the inputs passed by the CreateThread function
|
| 417 | + */
|
188 | 418 | DWORD WINAPI glRenderer::ThreadEntry(void *entry)
|
189 | 419 | {
|
190 | 420 | void **inputsin = (void**)entry;
|
— | — | @@ -191,249 +421,459 @@ |
192 | 422 | return This->_Entry();
|
193 | 423 | }
|
194 | 424 |
|
| 425 | +/**
|
| 426 | + * Creates an OpenGL texture.
|
| 427 | + * @param min,mag
|
| 428 | + * Minification and magnification filters for the OpenGL texture
|
| 429 | + * @param wraps,wrapt
|
| 430 | + * OpenGL texture wrap parameters
|
| 431 | + * @param width,height
|
| 432 | + * Width and height of the texture.
|
| 433 | + * @param texformat
|
| 434 | + * OpenGL format parameter for glTexImage2D
|
| 435 | + * @param texformat2
|
| 436 | + * OpenGL type parameter for glTexImage2D
|
| 437 | + * @param texformat3
|
| 438 | + * OpenGL internalformat parameter for glTexImage2D
|
| 439 | + * @return
|
| 440 | + * Number representing the texture created by OpenGL.
|
| 441 | + */
|
195 | 442 | GLuint glRenderer::MakeTexture(GLint min, GLint mag, GLint wraps, GLint wrapt, DWORD width, DWORD height, GLint texformat1, GLint texformat2, GLint texformat3)
|
196 | 443 | {
|
197 | | - EnterCriticalSection(&cs);
|
198 | | - inputs[0] = (void*)min;
|
199 | | - inputs[1] = (void*)mag;
|
200 | | - inputs[2] = (void*)wraps;
|
201 | | - inputs[3] = (void*)wrapt;
|
202 | | - inputs[4] = (void*)width;
|
203 | | - inputs[5] = (void*)height;
|
204 | | - inputs[6] = (void*)texformat1;
|
205 | | - inputs[7] = (void*)texformat2;
|
206 | | - inputs[8] = (void*)texformat3;
|
207 | | - SendMessage(hRenderWnd,GLEVENT_CREATE,0,0);
|
208 | | - LeaveCriticalSection(&cs);
|
209 | | - return (GLuint)outputs[0];
|
| 444 | + EnterCriticalSection(&commandcs);
|
| 445 | + AddQueue(OP_CREATE,0,20,9,4,&min,4,&mag,4,&wraps,4,&wrapt,4,&width,
|
| 446 | + 4,&height,4,&texformat1,4,&texformat2,4,&texformat3);
|
| 447 | + Sync(0);
|
| 448 | + LeaveCriticalSection(&commandcs);
|
| 449 | + return (GLuint)output;
|
210 | 450 | }
|
211 | 451 |
|
212 | | -int glRenderer::UploadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y,
|
| 452 | +
|
| 453 | +/**
|
| 454 | + * Uploads the content of a surface to an OpenGL texture.
|
| 455 | + * @param buffer
|
| 456 | + * Contains the contents of the surface
|
| 457 | + * @param bigbuffer
|
| 458 | + * Optional buffer to receive the rescaled surface contents, for when primary
|
| 459 | + * scaling is enabled.
|
| 460 | + * @param texture
|
| 461 | + * OpenGL texture name to upload to
|
| 462 | + * @param x,y
|
| 463 | + * Width and height of the surface
|
| 464 | + * @param bigx,bigy
|
| 465 | + * Width and height of the scaled surface buffer
|
| 466 | + * @param pitch
|
| 467 | + * Bytes from one line of graphics to the next in the surface
|
| 468 | + * @param bigpitch
|
| 469 | + * Pitch of the scaled surface buffer
|
| 470 | + * @param bpp
|
| 471 | + * Number of bits per surface pixel
|
| 472 | + * @param texformat
|
| 473 | + * OpenGL format parameter for glTexImage2D
|
| 474 | + * @param texformat2
|
| 475 | + * OpenGL type parameter for glTexImage2D
|
| 476 | + * @param texformat3
|
| 477 | + * OpenGL internalformat parameter for glTexImage2D
|
| 478 | + */
|
| 479 | +void glRenderer::UploadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y,
|
213 | 480 | int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2, int texformat3)
|
214 | 481 | {
|
215 | | - EnterCriticalSection(&cs);
|
216 | | - MSG Msg;
|
217 | | - inputs[0] = buffer;
|
218 | | - inputs[1] = bigbuffer;
|
219 | | - inputs[2] = (void*)texture;
|
220 | | - inputs[3] = (void*)x;
|
221 | | - inputs[4] = (void*)y;
|
222 | | - inputs[5] = (void*)bigx;
|
223 | | - inputs[6] = (void*)bigy;
|
224 | | - inputs[7] = (void*)pitch;
|
225 | | - inputs[8] = (void*)bigpitch;
|
226 | | - inputs[9] = (void*)bpp;
|
227 | | - inputs[10] = (void*)texformat;
|
228 | | - inputs[11] = (void*)texformat2;
|
229 | | - inputs[12] = (void*)texformat3;
|
230 | | - wndbusy = true;
|
231 | | - SendMessage(hRenderWnd,GLEVENT_UPLOAD,0,0);
|
232 | | - while(wndbusy)
|
233 | | - {
|
234 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
235 | | - {
|
236 | | - TranslateMessage(&Msg);
|
237 | | - DispatchMessage(&Msg);
|
238 | | - }
|
239 | | - Sleep(0);
|
240 | | - }
|
241 | | - LeaveCriticalSection(&cs);
|
242 | | - return (int)outputs[0];
|
| 482 | + EnterCriticalSection(&commandcs);
|
| 483 | + AddQueue(OP_UPLOAD,0,28,13,4,&buffer,4,&bigbuffer,4,&texture,4,&x,4,&y,4,&bigx,
|
| 484 | + 4,&bigy,4,&pitch,4,&bigpitch,4,&bpp,4,&texformat,4,&texformat2,4,&texformat3);
|
| 485 | + Sync(0);
|
| 486 | + LeaveCriticalSection(&commandcs);
|
243 | 487 | }
|
244 | 488 |
|
245 | | -int glRenderer::DownloadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y,
|
| 489 | +/**
|
| 490 | + * Downloads the contents of an OpenGL texture to a surface buffer.
|
| 491 | + * @param buffer
|
| 492 | + * Buffer to receive the surface contents
|
| 493 | + * @param bigbuffer
|
| 494 | + * Optional buffer to receive the rescaled surface contents, for when primary
|
| 495 | + * scaling is enabled.
|
| 496 | + * @param texture
|
| 497 | + * OpenGL texture name to download from
|
| 498 | + * @param x,y
|
| 499 | + * Width and height of the surface
|
| 500 | + * @param bigx,bigy
|
| 501 | + * Width and height of the scaled surface buffer
|
| 502 | + * @param pitch
|
| 503 | + * Bytes from one line of graphics to the next in the surface
|
| 504 | + * @param bigpitch
|
| 505 | + * Pitch of the scaled surface buffer
|
| 506 | + * @param bpp
|
| 507 | + * Number of bits per surface pixel
|
| 508 | + * @param texformat
|
| 509 | + * OpenGL format parameter for glGetTexImage
|
| 510 | + * @param texformat2
|
| 511 | + * OpenGL type parameter for glGetTexImage
|
| 512 | + */
|
| 513 | +void glRenderer::DownloadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y,
|
246 | 514 | int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2)
|
247 | 515 | {
|
248 | | - EnterCriticalSection(&cs);
|
249 | | - MSG Msg;
|
250 | | - inputs[0] = buffer;
|
251 | | - inputs[1] = bigbuffer;
|
252 | | - inputs[2] = (void*)texture;
|
253 | | - inputs[3] = (void*)x;
|
254 | | - inputs[4] = (void*)y;
|
255 | | - inputs[5] = (void*)bigx;
|
256 | | - inputs[6] = (void*)bigy;
|
257 | | - inputs[7] = (void*)pitch;
|
258 | | - inputs[8] = (void*)bigpitch;
|
259 | | - inputs[9] = (void*)bpp;
|
260 | | - inputs[10] = (void*)texformat;
|
261 | | - inputs[11] = (void*)texformat2;
|
262 | | - wndbusy = true;
|
263 | | - SendMessage(hRenderWnd,GLEVENT_DOWNLOAD,0,0);
|
264 | | - while(wndbusy)
|
265 | | - {
|
266 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
267 | | - {
|
268 | | - TranslateMessage(&Msg);
|
269 | | - DispatchMessage(&Msg);
|
270 | | - }
|
271 | | - Sleep(0);
|
272 | | - }
|
273 | | - LeaveCriticalSection(&cs);
|
274 | | - return (int)outputs[0];
|
| 516 | + EnterCriticalSection(&commandcs);
|
| 517 | + AddQueue(OP_DOWNLOAD,0,26,12,4,&buffer,4,&bigbuffer,4,&texture,4,&x,4,&y,4,&bigx,
|
| 518 | + 4,&bigy,4,&pitch,4,&bigpitch,4,&bpp,4,&texformat,4,&texformat2);
|
| 519 | + Sync(0);
|
| 520 | + LeaveCriticalSection(&commandcs);
|
275 | 521 | }
|
276 | 522 |
|
| 523 | +/**
|
| 524 | + * Deletes an OpenGL texture.
|
| 525 | + * @param texture
|
| 526 | + * OpenGL texture to be deleted
|
| 527 | + */
|
277 | 528 | void glRenderer::DeleteTexture(GLuint texture)
|
278 | 529 | {
|
279 | | - EnterCriticalSection(&cs);
|
280 | | - inputs[0] = (void*)texture;
|
281 | | - SendMessage(hRenderWnd,GLEVENT_DELETETEX,0,0);
|
282 | | - LeaveCriticalSection(&cs);
|
| 530 | + EnterCriticalSection(&commandcs);
|
| 531 | + AddQueue(OP_DELETETEX,0,4,1,4,&texture);
|
| 532 | + LeaveCriticalSection(&commandcs);
|
283 | 533 | }
|
284 | 534 |
|
| 535 | +/**
|
| 536 | + * Copies the contents of one surface to another.
|
| 537 | + * @param lpDestRect
|
| 538 | + * Pointer to the coordinates to blit to. If NULL, blits to the entire surface.
|
| 539 | + * @param src
|
| 540 | + * Surface to be used as the source.
|
| 541 | + * @param dest
|
| 542 | + * Surface to blit to.
|
| 543 | + * @param lpSrcRect
|
| 544 | + * Pointer of the coordinates to blit from on the source surface. If NULL, the
|
| 545 | + * entire surface will be used.
|
| 546 | + * @param dwFlags
|
| 547 | + * Flags to determine the behavior of the blitter. Certain flags control the
|
| 548 | + * synchronization of the operation:
|
| 549 | + * - DDBLT_ASYNC: Adds the command to the queue. If the queue is full, returns
|
| 550 | + * DDERR_WASSTILLDRAWING.
|
| 551 | + * - DDBLT_DONOTWAIT: Fails and returns DDERR_WASSTILLDRAWING if the queue is full.
|
| 552 | + * - DDBLT_WAIT: Waits until the Blt command is processed before returning.
|
| 553 | + * @param lpDDBltFx
|
| 554 | + * Effect parameters for the Blt operation.
|
| 555 | + * @return
|
| 556 | + * DD_OK if the call succeeds, or DDERR_WASSTILLDRAWING if busy.
|
| 557 | + */
|
285 | 558 | HRESULT glRenderer::Blt(LPRECT lpDestRect, glDirectDrawSurface7 *src,
|
286 | 559 | glDirectDrawSurface7 *dest, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
|
287 | 560 | {
|
288 | | - MSG Msg;
|
289 | | - EnterCriticalSection(&cs);
|
290 | | - inputs[0] = lpDestRect;
|
291 | | - inputs[1] = src;
|
292 | | - inputs[2] = dest;
|
293 | | - inputs[3] = lpSrcRect;
|
294 | | - inputs[4] = (void*)dwFlags;
|
295 | | - inputs[5] = lpDDBltFx;
|
296 | | - wndbusy = true;
|
297 | | - SendMessage(hRenderWnd,GLEVENT_BLT,0,0);
|
298 | | - while(wndbusy)
|
| 561 | + DWORD nullfx = 0xFFFFFFFF;
|
| 562 | + RECT emptyrect = nullrect;
|
| 563 | + EnterCriticalSection(&commandcs);
|
| 564 | + int syncmode = 0;
|
| 565 | + if(dwFlags & DDBLT_ASYNC) syncmode = 1;
|
| 566 | + if(dwFlags & DDBLT_DONOTWAIT) syncmode = 2;
|
| 567 | + if(!lpSrcRect) lpSrcRect = &emptyrect;
|
| 568 | + if(!lpDestRect) lpDestRect = &emptyrect;
|
| 569 | + int fxsize = 4;
|
| 570 | + if(lpDDBltFx) fxsize = sizeof(DDBLTFX);
|
| 571 | + else lpDDBltFx = (LPDDBLTFX)&nullfx;
|
| 572 | + if(AddQueue(OP_BLT,syncmode,5+(sizeof(RECT)/2)+(fxsize/4),6,sizeof(RECT),lpDestRect,4,&src,
|
| 573 | + 4,&dest,sizeof(RECT),lpSrcRect,4,&dwFlags,fxsize,lpDDBltFx))
|
299 | 574 | {
|
300 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
301 | | - {
|
302 | | - TranslateMessage(&Msg);
|
303 | | - DispatchMessage(&Msg);
|
304 | | - }
|
305 | | - Sleep(0);
|
| 575 | + LeaveCriticalSection(&commandcs);
|
| 576 | + return DDERR_WASSTILLDRAWING;
|
306 | 577 | }
|
307 | | - LeaveCriticalSection(&cs);
|
308 | | - return (HRESULT)outputs[0];
|
| 578 | + if(dwFlags & DDBLT_WAIT) Sync(0);
|
| 579 | + LeaveCriticalSection(&commandcs);
|
| 580 | + return DD_OK;
|
309 | 581 | }
|
310 | 582 |
|
| 583 | +/**
|
| 584 | + * Updates the display with the current primary texture.
|
| 585 | + * @param texture
|
| 586 | + * Texture to use as the primary
|
| 587 | + * @param paltex
|
| 588 | + * Texture that contains the color palette for 8-bit modes
|
| 589 | + * @param dest
|
| 590 | + * Destination surface to be updated
|
| 591 | + * @param src
|
| 592 | + * Source surface to be updated
|
| 593 | + */
|
311 | 594 | void glRenderer::DrawScreen(GLuint texture, GLuint paltex, glDirectDrawSurface7 *dest, glDirectDrawSurface7 *src)
|
312 | 595 | {
|
313 | | - MSG Msg;
|
314 | | - EnterCriticalSection(&cs);
|
315 | | - inputs[0] = (void*)texture;
|
316 | | - inputs[1] = (void*)paltex;
|
317 | | - inputs[2] = dest;
|
318 | | - inputs[3] = src;
|
319 | | - wndbusy = true;
|
320 | | - SendMessage(hRenderWnd,GLEVENT_DRAWSCREEN,0,0);
|
321 | | - while(wndbusy)
|
322 | | - {
|
323 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
324 | | - {
|
325 | | - TranslateMessage(&Msg);
|
326 | | - DispatchMessage(&Msg);
|
327 | | - }
|
328 | | - Sleep(0);
|
329 | | - }
|
330 | | - LeaveCriticalSection(&cs);
|
| 596 | + EnterCriticalSection(&commandcs);
|
| 597 | + AddQueue(OP_DRAWSCREEN,0,10,4,4,&texture,4,&paltex,4,&dest,4,&src);
|
| 598 | + Sync(0);
|
| 599 | + LeaveCriticalSection(&commandcs);
|
331 | 600 | }
|
332 | 601 |
|
| 602 | +/**
|
| 603 | + * Ensures the renderer is set up for handling Direct3D commands.
|
| 604 | + * @param zbuffer
|
| 605 | + * Nonzero if a Z buffer is present.
|
| 606 | + */
|
333 | 607 | void glRenderer::InitD3D(int zbuffer)
|
334 | 608 | {
|
335 | | - MSG Msg;
|
336 | | - EnterCriticalSection(&cs);
|
337 | | - wndbusy = true;
|
338 | | - inputs[0] = (void*)zbuffer;
|
339 | | - SendMessage(hRenderWnd,GLEVENT_INITD3D,0,0);
|
340 | | - while(wndbusy)
|
341 | | - {
|
342 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
343 | | - {
|
344 | | - TranslateMessage(&Msg);
|
345 | | - DispatchMessage(&Msg);
|
346 | | - }
|
347 | | - Sleep(0);
|
348 | | - }
|
349 | | - LeaveCriticalSection(&cs);
|
| 609 | + EnterCriticalSection(&commandcs);
|
| 610 | + AddQueue(OP_INITD3D,0,4,1,4,zbuffer);
|
| 611 | + LeaveCriticalSection(&commandcs);
|
350 | 612 | }
|
351 | 613 |
|
| 614 | +/**
|
| 615 | + * Clears the viewport.
|
| 616 | + * @param target
|
| 617 | + * Surface to be cleared
|
| 618 | + * @param dwCount
|
| 619 | + * Number of rects to use to clear the buffer, or 0 to clear the entire buffer.
|
| 620 | + * @param lpRects
|
| 621 | + * Pointer to rects to clear.
|
| 622 | + * @param dwFlags
|
| 623 | + * Flags to determine which surfaces to clear.
|
| 624 | + * @param dwColor
|
| 625 | + * Color value to fill the surface with.
|
| 626 | + * @param dvZ
|
| 627 | + * Value to fill the Z buffer with.
|
| 628 | + * @param dwStencil
|
| 629 | + * Value to fill the stencil buffer with.
|
| 630 | + * @return
|
| 631 | + * Returns D3D_OK
|
| 632 | + */
|
352 | 633 | HRESULT glRenderer::Clear(glDirectDrawSurface7 *target, DWORD dwCount, LPD3DRECT lpRects, DWORD dwFlags, DWORD dwColor, D3DVALUE dvZ, DWORD dwStencil)
|
353 | 634 | {
|
354 | | - MSG Msg;
|
355 | | - EnterCriticalSection(&cs);
|
356 | | - wndbusy = true;
|
357 | | - inputs[0] = target;
|
358 | | - inputs[1] = (void*)dwCount;
|
359 | | - inputs[2] = lpRects;
|
360 | | - inputs[3] = (void*)dwFlags;
|
361 | | - inputs[4] = (void*)dwColor;
|
362 | | - memcpy(&inputs[5],&dvZ,4);
|
363 | | - inputs[6] = (void*)dwStencil;
|
364 | | - SendMessage(hRenderWnd,GLEVENT_CLEAR,0,0);
|
365 | | - while(wndbusy)
|
366 | | - {
|
367 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
368 | | - {
|
369 | | - TranslateMessage(&Msg);
|
370 | | - DispatchMessage(&Msg);
|
371 | | - }
|
372 | | - Sleep(0);
|
373 | | - }
|
374 | | - LeaveCriticalSection(&cs);
|
375 | | - return (HRESULT)outputs[0];
|
| 635 | + EnterCriticalSection(&commandcs);
|
| 636 | + int rectsize = dwCount * sizeof(D3DRECT);
|
| 637 | + AddQueue(OP_CLEAR,0,15+(rectsize/4),7,4,&target,4,&dwCount,rectsize,lpRects,
|
| 638 | + 4,dwFlags,4,dwColor,4,dvZ,4,dwStencil);
|
| 639 | + LeaveCriticalSection(&commandcs);
|
| 640 | + return D3D_OK;
|
376 | 641 | }
|
377 | 642 |
|
| 643 | +/**
|
| 644 | + * Issues a glFlush command and empties the queue.
|
| 645 | + */
|
378 | 646 | void glRenderer::Flush()
|
379 | 647 | {
|
380 | | - MSG Msg;
|
381 | | - EnterCriticalSection(&cs);
|
382 | | - wndbusy = true;
|
383 | | - SendMessage(hRenderWnd,GLEVENT_FLUSH,0,0);
|
384 | | - while(wndbusy)
|
385 | | - {
|
386 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
387 | | - {
|
388 | | - TranslateMessage(&Msg);
|
389 | | - DispatchMessage(&Msg);
|
390 | | - }
|
391 | | - Sleep(0);
|
392 | | - }
|
393 | | - LeaveCriticalSection(&cs);
|
| 648 | + EnterCriticalSection(&commandcs);
|
| 649 | + AddQueue(OP_CLEAR,0,2,0,0,NULL);
|
| 650 | + Sync(0);
|
| 651 | + LeaveCriticalSection(&commandcs);
|
394 | 652 | }
|
395 | 653 |
|
396 | | -HRESULT glRenderer::DrawPrimitives(glDirect3DDevice7 *device, GLenum mode, GLVERTEX *vertices, int *texformats, DWORD count, LPWORD indices,
|
397 | | - DWORD indexcount, DWORD flags)
|
| 654 | +/**
|
| 655 | + * Draws one or more primitives to the currently selected render target.
|
| 656 | + * @param device
|
| 657 | + * glDirect3DDevice7 interface to use for drawing
|
| 658 | + * @param mode
|
| 659 | + * OpenGL primitive drawing mode to use
|
| 660 | + * @param vertices
|
| 661 | + * Pointer to vertex data
|
| 662 | + * @param packed
|
| 663 | + * True if vertex data is packed (e.g. xyz,normal,texcoord,xyz,normal,etc.)
|
| 664 | + * @param texformats
|
| 665 | + * Pointer to texture coordinate formats used in the call
|
| 666 | + * @param count
|
| 667 | + * Number of vertices to copy to the draw command
|
| 668 | + * @param indices
|
| 669 | + * List of vertex indices to use in the drawing command, may be NULL for
|
| 670 | + * non-indexed mode.
|
| 671 | + * @param indexcount
|
| 672 | + * Number of vertex indices. May be 0 for non-indexed mode.
|
| 673 | + * @param flags
|
| 674 | + * Set to D3DDP_WAIT to wait until the queue has processed the call.
|
| 675 | + * @return
|
| 676 | + * D3D_OK if the call succeeds, or D3DERR_INVALIDVERTEXTYPE if the vertex format
|
| 677 | + * has no position coordinates.
|
| 678 | + */
|
| 679 | +HRESULT glRenderer::DrawPrimitives(glDirect3DDevice7 *device, GLenum mode, GLVERTEX *vertices, bool packed,
|
| 680 | + DWORD *texformats, DWORD count, LPWORD indices, DWORD indexcount, DWORD flags)
|
398 | 681 | {
|
399 | | - MSG Msg;
|
400 | | - EnterCriticalSection(&cs);
|
401 | | - wndbusy = true;
|
402 | | - inputs[0] = device;
|
403 | | - inputs[1] = (void*)mode;
|
404 | | - inputs[2] = vertices;
|
405 | | - inputs[3] = texformats;
|
406 | | - inputs[4] = (void*)count;
|
407 | | - inputs[5] = indices;
|
408 | | - inputs[6] = (void*)indexcount;
|
409 | | - inputs[7] = (void*)flags;
|
410 | | - SendMessage(hRenderWnd,GLEVENT_DRAWPRIMITIVES,0,0);
|
411 | | - while(wndbusy)
|
| 682 | + if(!vertices[0].data) return D3DERR_INVALIDVERTEXTYPE;
|
| 683 | + GLVERTEX vertdata[18];
|
| 684 | + EnterCriticalSection(&commandcs);
|
| 685 | + __int64 shader = device->SelectShader(vertices);
|
| 686 | + int vertsize = 0;
|
| 687 | + if(packed)
|
412 | 688 | {
|
413 | | - while(PeekMessage(&Msg,hRenderWnd,0,0,PM_REMOVE))
|
| 689 | + vertsize = vertices[0].stride * count;
|
| 690 | + AddQueue(OP_DRAWPRIMITIVES,0,NextMultipleOf4(40+(18*sizeof(GLVERTEX))+(8*sizeof(DWORD))+(indexcount*sizeof(WORD))+vertsize)/4,
|
| 691 | + 10,4,&device,4,&mode,18*sizeof(GLVERTEX),vertices,1,&packed,8*sizeof(DWORD),texformats,4,&count,indexcount*sizeof(WORD),
|
| 692 | + &indices,4,&indexcount,4,&flags,8,&shader,vertsize,vertices[0].data);
|
| 693 | + }
|
| 694 | + else
|
| 695 | + {
|
| 696 | + for(int i = 0; i < 18; i++)
|
414 | 697 | {
|
415 | | - TranslateMessage(&Msg);
|
416 | | - DispatchMessage(&Msg);
|
| 698 | + vertdata[i].stride = vertices[i].stride;
|
| 699 | + if(vertices[i].data)
|
| 700 | + {
|
| 701 | + vertdata[i].data = (void*)vertsize;
|
| 702 | + vertsize += (vertices[i].stride * count);
|
| 703 | + }
|
| 704 | + else vertdata[i].data = (void*)-1;
|
417 | 705 | }
|
418 | | - Sleep(0);
|
| 706 | + FIXME("glRenderer::DrawPrimitives: Add Strided Vertex format");
|
| 707 | + AddQueue(OP_DRAWPRIMITIVES,0,NextMultipleOf4(32+(18*sizeof(GLVERTEX))+(8*sizeof(DWORD))+(indexcount*sizeof(WORD))+vertsize)/4,
|
| 708 | + 10,4,&device,4,&mode,18*sizeof(GLVERTEX),vertdata,1,packed,8*sizeof(DWORD),texformats,4,count,indexcount*sizeof(WORD),
|
| 709 | + indices,4,indexcount,4,flags,vertsize,vertdata[0].data);
|
419 | 710 | }
|
420 | | - return (HRESULT)outputs[0];
|
| 711 | + if(flags & D3DDP_WAIT) Sync(0);
|
| 712 | + LeaveCriticalSection(&commandcs);
|
| 713 | + return D3D_OK;
|
421 | 714 | }
|
422 | 715 |
|
| 716 | +/**
|
| 717 | + * Sets one or more render states in the glRenderer class
|
| 718 | + * @param index
|
| 719 | + * Index of the render state(s) to set
|
| 720 | + * @param count
|
| 721 | + * Number of states to set at once
|
| 722 | + * @param data
|
| 723 | + * Pointer to state data to copy
|
| 724 | + * @remark
|
| 725 | + * If the render thread is not currently running, this function will immediately
|
| 726 | + * copy the data to the renderer. Otherwise, it will add a command to the queue.
|
| 727 | + */
|
| 728 | +void glRenderer::SetRenderState(DWORD index, DWORD count, DWORD *data)
|
| 729 | +{
|
| 730 | + EnterCriticalSection(&commandcs);
|
| 731 | + if(!running) memcpy(&renderstate[index],data,count*sizeof(DWORD));
|
| 732 | + else AddQueue(OP_SETRENDERSTATE,0,4+count,2,4,&index,count*4,data);
|
| 733 | + LeaveCriticalSection(&commandcs);
|
| 734 | +}
|
423 | 735 |
|
| 736 | +/**
|
| 737 | + * Sets one or more Direct3D matrices in the glRenderer class
|
| 738 | + * @param index
|
| 739 | + * Index of the matrix or matrices to set
|
| 740 | + * @param count
|
| 741 | + * Number of matrices to set at once
|
| 742 | + * @param data
|
| 743 | + * Pointer to matrices to copy
|
| 744 | + * @remark
|
| 745 | + * If the render thread is not currently running, this function will immediately
|
| 746 | + * copy the data to the renderer. Otherwise, it will add a command to the queue.
|
| 747 | + */
|
| 748 | +void glRenderer::SetMatrix(DWORD index, DWORD count, D3DMATRIX *data)
|
| 749 | +{
|
| 750 | + EnterCriticalSection(&commandcs);
|
| 751 | + if(!running) memcpy(&renderstate[index],data,count*sizeof(D3DMATRIX));
|
| 752 | + else AddQueue(OP_SETMATRIX,0,4+((count*sizeof(D3DMATRIX))/4),2,4,&index,count*4,data);
|
| 753 | + LeaveCriticalSection(&commandcs);
|
| 754 | +}
|
| 755 | +
|
| 756 | +/**
|
| 757 | + * Main loop for glRenderer class
|
| 758 | + * @return
|
| 759 | + * Returns 0 to signal successful thread termination
|
| 760 | + */
|
424 | 761 | DWORD glRenderer::_Entry()
|
425 | 762 | {
|
| 763 | + DWORD size;
|
426 | 764 | MSG Msg;
|
427 | | - EnterCriticalSection(&cs);
|
428 | 765 | _InitGL((int)inputs[0],(int)inputs[1],(int)inputs[2],(int)inputs[3],(HWND)inputs[4],(glDirectDraw7*)inputs[5]);
|
429 | | - LeaveCriticalSection(&cs);
|
430 | | - while(GetMessage(&Msg, NULL, 0, 0) > 0)
|
| 766 | + dead = false;
|
| 767 | + queue = (LPDWORD)malloc(1048576);
|
| 768 | + queuesize = 1048576/sizeof(DWORD);
|
| 769 | + queuelength = queue_read = queue_write = syncsize = 0;
|
| 770 | + SetEvent(busy);
|
| 771 | + start = CreateEvent(NULL,TRUE,FALSE,NULL);
|
| 772 | + ResetEvent(start);
|
| 773 | + sync = CreateEvent(NULL,TRUE,FALSE,NULL);
|
| 774 | + queueloop:
|
| 775 | + MsgWaitForMultipleObjects(1,&start,FALSE,INFINITE,QS_ALLEVENTS);
|
| 776 | + if(PeekMessage(&Msg,NULL,0,0,PM_REMOVE))
|
431 | 777 | {
|
432 | 778 | TranslateMessage(&Msg);
|
433 | 779 | DispatchMessage(&Msg);
|
434 | 780 | }
|
| 781 | + if(queuelength)
|
| 782 | + {
|
| 783 | + running = true;
|
| 784 | + switch(queue[queue_read])
|
| 785 | + {
|
| 786 | + case OP_NULL:
|
| 787 | + default:
|
| 788 | + break;
|
| 789 | + case OP_DELETE:
|
| 790 | + DestroyWindow(hRenderWnd);
|
| 791 | + break;
|
| 792 | + case OP_CREATE:
|
| 793 | + if(queue[queue_read+1] != 20) break;
|
| 794 | + output = (void*)_MakeTexture(queue[queue_read+3],queue[queue_read+5],queue[queue_read+7],queue[queue_read+9],
|
| 795 | + queue[queue_read+11],queue[queue_read+13],queue[queue_read+15],queue[queue_read+17],queue[queue_read+19]);
|
| 796 | + break;
|
| 797 | + case OP_UPLOAD:
|
| 798 | + if(queue[queue_read+1] != 28) break;
|
| 799 | + _UploadTexture((char*)queue[queue_read+3],(char*)queue[queue_read+5],queue[queue_read+7],queue[queue_read+9],
|
| 800 | + queue[queue_read+11],queue[queue_read+13],queue[queue_read+15],queue[queue_read+17],queue[queue_read+19],
|
| 801 | + queue[queue_read+21],queue[queue_read+23],queue[queue_read+25],queue[queue_read+27]);
|
| 802 | + break;
|
| 803 | + case OP_DOWNLOAD:
|
| 804 | + if(queue[queue_read+1] != 26) break;
|
| 805 | + _DownloadTexture((char*)queue[queue_read+3],(char*)queue[queue_read+5],queue[queue_read+7],queue[queue_read+9],
|
| 806 | + queue[queue_read+11],queue[queue_read+13],queue[queue_read+15],queue[queue_read+17],queue[queue_read+19],
|
| 807 | + queue[queue_read+21],queue[queue_read+23],queue[queue_read+25]);
|
| 808 | + break;
|
| 809 | + case OP_DELETETEX:
|
| 810 | + if(queue[queue_read+1] != 4) break;
|
| 811 | + _DeleteTexture(queue[queue_read+3]);
|
| 812 | + break;
|
| 813 | + case OP_BLT:
|
| 814 | + if(queue[queue_read+1] < 5) break;
|
| 815 | + _Blt((LPRECT)&queue[queue_read+3],(glDirectDrawSurface7*)queue[queue_read+4+(sizeof(RECT)/4)],
|
| 816 | + (glDirectDrawSurface7*)queue[queue_read+6+(sizeof(RECT)/4)],(LPRECT)&queue[queue_read+8+(sizeof(RECT)/4)],
|
| 817 | + queue[queue_read+9+(sizeof(RECT)/2)],(LPDDBLTFX)&queue[queue_read+11+(sizeof(RECT)/2)]);
|
| 818 | + break;
|
| 819 | + case OP_DRAWSCREEN:
|
| 820 | + if(queue[queue_read+1] != 10) break;
|
| 821 | + _DrawScreen(queue[queue_read+3],queue[queue_read+5],(glDirectDrawSurface7*)queue[queue_read+7],
|
| 822 | + (glDirectDrawSurface7*)queue[queue_read+9]);
|
| 823 | + break;
|
| 824 | + case OP_INITD3D:
|
| 825 | + if(queue[queue_read+1] != 4) break;
|
| 826 | + _InitD3D(queue[queue_read+3]);
|
| 827 | + break;
|
| 828 | + case OP_CLEAR:
|
| 829 | + if(queue[queue_read+1] < 15) break;
|
| 830 | + size = queue[queue_read+1] - 15;
|
| 831 | + if(!size) _Clear((glDirectDrawSurface7*)queue[queue_read+3],queue[queue_read+5],NULL,
|
| 832 | + queue[queue_read+8],queue[queue_read+10],queue[queue_read+12],queue[queue_read+14]);
|
| 833 | + else _Clear((glDirectDrawSurface7*)queue[queue_read+3],queue[queue_read+5],(LPD3DRECT)&queue[queue_read+7],
|
| 834 | + queue[queue_read+8+size],queue[queue_read+10+size],queue[queue_read+12+size],
|
| 835 | + queue[queue_read+14+size]);
|
| 836 | + break;
|
| 837 | + case OP_FLUSH:
|
| 838 | + _Flush();
|
| 839 | + break;
|
| 840 | + }
|
| 841 | + EnterCriticalSection(&queuecs);
|
| 842 | + queuelength--;
|
| 843 | + queue_read+=queue[queue_read+1];
|
| 844 | + if((queue_read >= syncsize) && syncsize != 0) SetEvent(sync);
|
| 845 | + }
|
| 846 | + else EnterCriticalSection(&queuecs);
|
| 847 | + if(!queuelength)
|
| 848 | + {
|
| 849 | + ResetEvent(start);
|
| 850 | + queue_read = 0;
|
| 851 | + queue_write = 0;
|
| 852 | + running = false;
|
| 853 | + SetEvent(sync);
|
| 854 | + }
|
| 855 | + LeaveCriticalSection(&queuecs);
|
| 856 | + if(!dead) goto queueloop;
|
| 857 | + free(queue);
|
| 858 | + queue = NULL;
|
435 | 859 | return 0;
|
436 | 860 | }
|
437 | 861 |
|
| 862 | +/**
|
| 863 | + * Creates a render window and initializes OpenGL.
|
| 864 | + * @param width,height
|
| 865 | + * Width and height of the render window.
|
| 866 | + * @param bpp
|
| 867 | + * Color depth of the screen.
|
| 868 | + * @param fullscreen
|
| 869 | + * True if full screen mode is requested.
|
| 870 | + * @param hWnd
|
| 871 | + * Handle to the window to use as the renderer. If NULL, then creates a
|
| 872 | + * transparent overlay window.
|
| 873 | + * @param glDD7
|
| 874 | + * Pointer to the glDirectDraw7 interface that creates the renderer.
|
| 875 | + * @return
|
| 876 | + * TRUE if OpenGL has been initialized, FALSE otherwise.
|
| 877 | + */
|
438 | 878 | BOOL glRenderer::_InitGL(int width, int height, int bpp, int fullscreen, HWND hWnd, glDirectDraw7 *glDD7)
|
439 | 879 | {
|
440 | 880 | ddInterface = glDD7;
|
— | — | @@ -469,8 +909,13 @@ |
470 | 910 | {
|
471 | 911 | width = GetSystemMetrics(SM_CXSCREEN);
|
472 | 912 | height = GetSystemMetrics(SM_CYSCREEN);
|
| 913 | +#ifdef _DEBUG
|
| 914 | + hRenderWnd = CreateWindowExA(WS_EX_TOOLWINDOW|WS_EX_LAYERED|WS_EX_TRANSPARENT,
|
| 915 | + "DXGLRenderWindow","Renderer",WS_POPUP,0,0,width,height,0,0,NULL,this);
|
| 916 | +#else
|
473 | 917 | hRenderWnd = CreateWindowExA(WS_EX_TOOLWINDOW|WS_EX_LAYERED|WS_EX_TRANSPARENT|WS_EX_TOPMOST,
|
474 | 918 | "DXGLRenderWindow","Renderer",WS_POPUP,0,0,width,height,0,0,NULL,this);
|
| 919 | +#endif
|
475 | 920 | hasHWnd = false;
|
476 | 921 | SetWindowPos(hRenderWnd,HWND_TOP,0,0,rectRender.right,rectRender.bottom,SWP_SHOWWINDOW|SWP_NOACTIVATE);
|
477 | 922 | }
|
— | — | @@ -526,7 +971,6 @@ |
527 | 972 | gllock = false;
|
528 | 973 | return FALSE;
|
529 | 974 | }
|
530 | | - wndbusy = false;
|
531 | 975 | gllock = false;
|
532 | 976 | InitGLExt();
|
533 | 977 | SetSwap(1);
|
— | — | @@ -573,7 +1017,7 @@ |
574 | 1018 | return TRUE;
|
575 | 1019 | }
|
576 | 1020 |
|
577 | | -HRESULT glRenderer::_Blt(LPRECT lpDestRect, glDirectDrawSurface7 *src,
|
| 1021 | +void glRenderer::_Blt(LPRECT lpDestRect, glDirectDrawSurface7 *src,
|
578 | 1022 | glDirectDrawSurface7 *dest, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx)
|
579 | 1023 | {
|
580 | 1024 | LONG sizes[6];
|
— | — | @@ -588,7 +1032,6 @@ |
589 | 1033 | if(memcmp(&r2,&r,sizeof(RECT)))
|
590 | 1034 | SetWindowPos(hRenderWnd,NULL,0,0,r.right,r.bottom,SWP_SHOWWINDOW);
|
591 | 1035 | }
|
592 | | - wndbusy = false;
|
593 | 1036 | ddInterface->GetSizes(sizes);
|
594 | 1037 | int error;
|
595 | 1038 | error = SetFBO(dest->texture,0,false);
|
— | — | @@ -729,7 +1172,7 @@ |
730 | 1173 | (ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE)) ||
|
731 | 1174 | ((ddsd.ddsCaps.dwCaps & DDSCAPS_PRIMARYSURFACE) &&
|
732 | 1175 | !(ddsd.ddsCaps.dwCaps & DDSCAPS_FLIP)))_DrawScreen(dest->texture,dest->paltex,dest,dest);
|
733 | | - return DD_OK;
|
| 1176 | + SetEvent(busy);
|
734 | 1177 | }
|
735 | 1178 |
|
736 | 1179 | GLuint glRenderer::_MakeTexture(GLint min, GLint mag, GLint wraps, GLint wrapt, DWORD width, DWORD height, GLint texformat1, GLint texformat2, GLint texformat3)
|
— | — | @@ -799,7 +1242,6 @@ |
800 | 1243 | if(memcmp(&r2,&r,sizeof(RECT)))
|
801 | 1244 | SetWindowPos(hRenderWnd,NULL,0,0,r.right,r.bottom,SWP_SHOWWINDOW);
|
802 | 1245 | }
|
803 | | - wndbusy = false;
|
804 | 1246 | RECT *viewrect = &r2;
|
805 | 1247 | SetSwap(swapinterval);
|
806 | 1248 | LONG sizes[6];
|
— | — | @@ -949,14 +1391,15 @@ |
950 | 1392 | void glRenderer::_DeleteTexture(GLuint texture)
|
951 | 1393 | {
|
952 | 1394 | glDeleteTextures(1,&texture);
|
| 1395 | + SetEvent(busy);
|
953 | 1396 | }
|
954 | 1397 |
|
955 | 1398 | void glRenderer::_InitD3D(int zbuffer)
|
956 | 1399 | {
|
957 | | - wndbusy = false;
|
| 1400 | + if(zbuffer) glEnable(GL_DEPTH_TEST);
|
| 1401 | + SetEvent(busy);
|
958 | 1402 | glHint(GL_PERSPECTIVE_CORRECTION_HINT,GL_NICEST);
|
959 | 1403 | GLfloat ambient[] = {0.0,0.0,0.0,0.0};
|
960 | | - if(zbuffer) glEnable(GL_DEPTH_TEST);
|
961 | 1404 | glDepthFunc(GL_LEQUAL);
|
962 | 1405 | glDisable(GL_DITHER);
|
963 | 1406 | }
|
— | — | @@ -965,13 +1408,9 @@ |
966 | 1409 | {
|
967 | 1410 | if(dwCount)
|
968 | 1411 | {
|
969 | | - outputs[0] = (void*)DDERR_INVALIDPARAMS;
|
970 | 1412 | FIXME("glDirect3DDevice7::Clear: Cannot clear rects yet.");
|
971 | | - wndbusy = false;
|
972 | 1413 | return;
|
973 | 1414 | }
|
974 | | - outputs[0] = (void*)D3D_OK;
|
975 | | - wndbusy = false;
|
976 | 1415 | GLfloat color[4];
|
977 | 1416 | dwordto4float(dwColor,color);
|
978 | 1417 | if(target->zbuffer) SetFBO(target->texture,target->GetZBuffer()->texture,target->GetZBuffer()->hasstencil);
|
— | — | @@ -995,12 +1434,13 @@ |
996 | 1435 | glClear(clearbits);
|
997 | 1436 | if(target->zbuffer) target->zbuffer->dirty |= 2;
|
998 | 1437 | target->dirty |= 2;
|
| 1438 | + SetEvent(busy);
|
999 | 1439 | }
|
1000 | 1440 |
|
1001 | 1441 | void glRenderer::_Flush()
|
1002 | 1442 | {
|
1003 | | - wndbusy = false;
|
1004 | 1443 | glFlush();
|
| 1444 | + SetEvent(busy);
|
1005 | 1445 | }
|
1006 | 1446 |
|
1007 | 1447 | void glRenderer::_DrawPrimitives(glDirect3DDevice7 *device, GLenum mode, GLVERTEX *vertices, int *texformats, DWORD count, LPWORD indices,
|
— | — | @@ -1014,12 +1454,6 @@ |
1015 | 1455 | int i;
|
1016 | 1456 | if(vertices[1].data) transformed = true;
|
1017 | 1457 | else transformed = false;
|
1018 | | - if(!vertices[0].data)
|
1019 | | - {
|
1020 | | - outputs[0] = (void*)DDERR_INVALIDPARAMS;
|
1021 | | - wndbusy = false;
|
1022 | | - return;
|
1023 | | - }
|
1024 | 1458 | __int64 shader = device->SelectShader(vertices);
|
1025 | 1459 | SetShader(shader,device->texstages,texformats,0);
|
1026 | 1460 | _GENSHADER prog = genshaders[current_genshader].shader;
|
— | — | @@ -1102,11 +1536,11 @@ |
1103 | 1537 |
|
1104 | 1538 | }
|
1105 | 1539 | }
|
1106 | | - if(device->normal_dirty) device->UpdateNormalMatrix();
|
1107 | | - if(prog.uniforms[0] != -1) glUniformMatrix4fv(prog.uniforms[0],1,false,device->matWorld);
|
1108 | | - if(prog.uniforms[1] != -1) glUniformMatrix4fv(prog.uniforms[1],1,false,device->matView);
|
1109 | | - if(prog.uniforms[2] != -1) glUniformMatrix4fv(prog.uniforms[2],1,false,device->matProjection);
|
1110 | | - if(prog.uniforms[3] != -1) glUniformMatrix3fv(prog.uniforms[3],1,true,device->matNormal);
|
| 1540 | + if(normal_dirty) _UpdateNormalMatrix();
|
| 1541 | + if(prog.uniforms[0] != -1) glUniformMatrix4fv(prog.uniforms[0],1,false,(GLfloat*)&matrices[1]);
|
| 1542 | + if(prog.uniforms[1] != -1) glUniformMatrix4fv(prog.uniforms[1],1,false,(GLfloat*)&matrices[2]);
|
| 1543 | + if(prog.uniforms[2] != -1) glUniformMatrix4fv(prog.uniforms[2],1,false,(GLfloat*)&matrices[3]);
|
| 1544 | + if(prog.uniforms[3] != -1) glUniformMatrix3fv(prog.uniforms[3],1,true,(GLfloat*)&matrices[7]);
|
1111 | 1545 |
|
1112 | 1546 | if(prog.uniforms[15] != -1) glUniform4fv(prog.uniforms[15],1,(GLfloat*)&device->material.ambient);
|
1113 | 1547 | if(prog.uniforms[16] != -1) glUniform4fv(prog.uniforms[16],1,(GLfloat*)&device->material.diffuse);
|
— | — | @@ -1150,7 +1584,7 @@ |
1151 | 1585 | lightindex++;
|
1152 | 1586 | }
|
1153 | 1587 |
|
1154 | | - DWORD ambient = device->renderstate[D3DRENDERSTATE_AMBIENT];
|
| 1588 | + DWORD ambient = renderstate[D3DRENDERSTATE_AMBIENT];
|
1155 | 1589 | if(prog.uniforms[136] != -1)
|
1156 | 1590 | glUniform4f(prog.uniforms[136],RGBA_GETRED(ambient),RGBA_GETGREEN(ambient),
|
1157 | 1591 | RGBA_GETBLUE(ambient),RGBA_GETALPHA(ambient));
|
— | — | @@ -1187,11 +1621,32 @@ |
1188 | 1622 | if(device->glDDS7->zbuffer) device->glDDS7->zbuffer->dirty |= 2;
|
1189 | 1623 | device->glDDS7->dirty |= 2;
|
1190 | 1624 | if(flags & D3DDP_WAIT) glFlush();
|
1191 | | - outputs[0] = (void*)D3D_OK;
|
1192 | | - wndbusy = false;
|
| 1625 | + SetEvent(busy);
|
1193 | 1626 | return;
|
1194 | 1627 | }
|
| 1628 | +void glRenderer::_UpdateNormalMatrix()
|
| 1629 | +{
|
| 1630 | + GLfloat worldview[16];
|
| 1631 | + GLfloat tmp[16];
|
1195 | 1632 |
|
| 1633 | + ZeroMemory(&worldview,sizeof(D3DMATRIX));
|
| 1634 | + ZeroMemory(&tmp,sizeof(D3DMATRIX));
|
| 1635 | + __gluMultMatricesf((GLfloat*)&matrices[1],(GLfloat*)&matrices[2],worldview); // Get worldview
|
| 1636 | + if(__gluInvertMatrixf(worldview,tmp)) // Invert
|
| 1637 | + {
|
| 1638 | + memcpy((GLfloat*)&matrices[7],tmp,3*sizeof(GLfloat));
|
| 1639 | + memcpy((GLfloat*)&matrices[7]+3,tmp+4,3*sizeof(GLfloat));
|
| 1640 | + memcpy((GLfloat*)&matrices[7]+6,tmp+8,3*sizeof(GLfloat));
|
| 1641 | + }
|
| 1642 | + else
|
| 1643 | + {
|
| 1644 | + memcpy((GLfloat*)&matrices[7],worldview,3*sizeof(GLfloat));
|
| 1645 | + memcpy((GLfloat*)&matrices[7]+3,worldview+4,3*sizeof(GLfloat));
|
| 1646 | + memcpy((GLfloat*)&matrices[7]+6,worldview+8,3*sizeof(GLfloat));
|
| 1647 | + }
|
| 1648 | +
|
| 1649 | + normal_dirty = false;
|
| 1650 | +}
|
1196 | 1651 | LRESULT glRenderer::WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
|
1197 | 1652 | {
|
1198 | 1653 | int oldx,oldy;
|
— | — | @@ -1236,14 +1691,15 @@ |
1237 | 1692 | };
|
1238 | 1693 | if(hDC) ReleaseDC(hRenderWnd,hDC);
|
1239 | 1694 | hDC = NULL;
|
1240 | | - wndbusy = false;
|
1241 | 1695 | PostQuitMessage(0);
|
| 1696 | + dead = true;
|
1242 | 1697 | return 0;
|
1243 | 1698 | case WM_SETCURSOR:
|
1244 | 1699 | hParent = GetParent(hwnd);
|
1245 | 1700 | cursor = (HCURSOR)GetClassLong(hParent,GCL_HCURSOR);
|
1246 | 1701 | SetCursor(cursor);
|
1247 | | - return SendMessage(hParent,msg,wParam,lParam);
|
| 1702 | + PostMessage(hParent,msg,wParam,lParam);
|
| 1703 | + return 0;
|
1248 | 1704 | case WM_MOUSEMOVE:
|
1249 | 1705 | case WM_LBUTTONDOWN:
|
1250 | 1706 | case WM_LBUTTONUP:
|
— | — | @@ -1278,53 +1734,10 @@ |
1279 | 1735 | if(oldx >= sizes[2]) oldx = sizes[2]-1;
|
1280 | 1736 | if(oldy >= sizes[3]) oldy = sizes[3]-1;
|
1281 | 1737 | newpos = oldx + (oldy << 16);
|
1282 | | - return SendMessage(hParent,msg,wParam,newpos);
|
| 1738 | + PostMessage(hParent,msg,wParam,newpos);
|
1283 | 1739 | }
|
1284 | | - else return SendMessage(hParent,msg,wParam,lParam);
|
1285 | | - case GLEVENT_DELETE:
|
1286 | | - DestroyWindow(hRenderWnd);
|
| 1740 | + else PostMessage(hParent,msg,wParam,lParam);
|
1287 | 1741 | return 0;
|
1288 | | - case GLEVENT_CREATE:
|
1289 | | - outputs[0] = (void*)_MakeTexture((GLint)inputs[0],(GLint)inputs[1],(GLint)inputs[2],(GLint)inputs[3],
|
1290 | | - (DWORD)inputs[4],(DWORD)inputs[5],(GLint)inputs[6],(GLint)inputs[7],(GLint)inputs[8]);
|
1291 | | - return 0;
|
1292 | | - case GLEVENT_UPLOAD:
|
1293 | | - outputs[0] = (void*)_UploadTexture((char*)inputs[0],(char*)inputs[1],(GLuint)inputs[2],(int)inputs[3],
|
1294 | | - (int)inputs[4],(int)inputs[5],(int)inputs[6],(int)inputs[7],(int)inputs[8],(int)inputs[9],
|
1295 | | - (int)inputs[10],(int)inputs[11],(int)inputs[12]);
|
1296 | | - wndbusy = false;
|
1297 | | - return 0;
|
1298 | | - case GLEVENT_DOWNLOAD:
|
1299 | | - outputs[0] = (void*)_DownloadTexture((char*)inputs[0],(char*)inputs[1],(GLuint)inputs[2],(int)inputs[3],
|
1300 | | - (int)inputs[4],(int)inputs[5],(int)inputs[6],(int)inputs[7],(int)inputs[8],(int)inputs[9],
|
1301 | | - (int)inputs[10],(int)inputs[11]);
|
1302 | | - wndbusy = false;
|
1303 | | - return 0;
|
1304 | | - case GLEVENT_DELETETEX:
|
1305 | | - _DeleteTexture((GLuint)inputs[0]);
|
1306 | | - return 0;
|
1307 | | - case GLEVENT_BLT:
|
1308 | | - outputs[0] = (void*)_Blt((LPRECT)inputs[0],(glDirectDrawSurface7*)inputs[1],(glDirectDrawSurface7*)inputs[2],
|
1309 | | - (LPRECT)inputs[3],(DWORD)inputs[4],(LPDDBLTFX)inputs[5]);
|
1310 | | - return 0;
|
1311 | | - case GLEVENT_DRAWSCREEN:
|
1312 | | - _DrawScreen((GLuint)inputs[0],(GLuint)inputs[1],(glDirectDrawSurface7*)inputs[2],(glDirectDrawSurface7*)inputs[3]);
|
1313 | | - return 0;
|
1314 | | - case GLEVENT_INITD3D:
|
1315 | | - _InitD3D((int)inputs[0]);
|
1316 | | - return 0;
|
1317 | | - case GLEVENT_CLEAR:
|
1318 | | - memcpy(&tmpfloats[0],&inputs[5],4);
|
1319 | | - _Clear((glDirectDrawSurface7*)inputs[0],(DWORD)inputs[1],(LPD3DRECT)inputs[2],(DWORD)inputs[3],(DWORD)inputs[4],
|
1320 | | - tmpfloats[0],(DWORD)inputs[6]);
|
1321 | | - return 0;
|
1322 | | - case GLEVENT_FLUSH:
|
1323 | | - _Flush();
|
1324 | | - return 0;
|
1325 | | - case GLEVENT_DRAWPRIMITIVES:
|
1326 | | - _DrawPrimitives((glDirect3DDevice7*)inputs[0],(GLenum)inputs[1],(GLVERTEX*)inputs[2],(int*)inputs[3],(DWORD)inputs[4],
|
1327 | | - (LPWORD)inputs[5],(DWORD)inputs[6],(DWORD)inputs[7]);
|
1328 | | - return 0;
|
1329 | 1742 | default:
|
1330 | 1743 | return DefWindowProc(hwnd,msg,wParam,lParam);
|
1331 | 1744 | }
|
Index: ddraw/glRenderer.h |
— | — | @@ -52,20 +52,24 @@ |
53 | 53 |
|
54 | 54 | extern BltVertex bltvertices[4];
|
55 | 55 |
|
56 | | -#define GLEVENT_NULL WM_USER
|
57 | | -#define GLEVENT_DELETE WM_USER+1
|
58 | | -#define GLEVENT_CREATE WM_USER+2
|
59 | | -#define GLEVENT_UPLOAD WM_USER+3
|
60 | | -#define GLEVENT_DOWNLOAD WM_USER+4
|
61 | | -#define GLEVENT_DELETETEX WM_USER+5
|
62 | | -#define GLEVENT_BLT WM_USER+6
|
63 | | -#define GLEVENT_DRAWSCREEN WM_USER+7
|
64 | | -#define GLEVENT_INITD3D WM_USER+8
|
65 | | -#define GLEVENT_CLEAR WM_USER+9
|
66 | | -#define GLEVENT_FLUSH WM_USER+10
|
67 | | -#define GLEVENT_DRAWPRIMITIVES WM_USER+11
|
| 56 | +#define OP_NULL 0
|
| 57 | +#define OP_DELETE 1
|
| 58 | +#define OP_CREATE 2
|
| 59 | +#define OP_UPLOAD 3
|
| 60 | +#define OP_DOWNLOAD 4
|
| 61 | +#define OP_DELETETEX 5
|
| 62 | +#define OP_BLT 6
|
| 63 | +#define OP_DRAWSCREEN 7
|
| 64 | +#define OP_INITD3D 8
|
| 65 | +#define OP_CLEAR 9
|
| 66 | +#define OP_FLUSH 10
|
| 67 | +#define OP_DRAWPRIMITIVES 11
|
| 68 | +#define OP_SETRENDERSTATE 12
|
| 69 | +#define OP_SETMATRIX 13
|
68 | 70 |
|
| 71 | +#define OP_RESETQUEUE 0xFFFFFFFF
|
69 | 72 |
|
| 73 | +
|
70 | 74 | extern int swapinterval;
|
71 | 75 | extern inline void SetSwap(int swap);
|
72 | 76 |
|
— | — | @@ -79,8 +83,8 @@ |
80 | 84 | glRenderer(int width, int height, int bpp, bool fullscreen, HWND hwnd, glDirectDraw7 *glDD7);
|
81 | 85 | ~glRenderer();
|
82 | 86 | static DWORD WINAPI ThreadEntry(void *entry);
|
83 | | - int UploadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2, int texformat3);
|
84 | | - int DownloadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2);
|
| 87 | + void UploadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2, int texformat3);
|
| 88 | + void DownloadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2);
|
85 | 89 | HRESULT Blt(LPRECT lpDestRect, glDirectDrawSurface7 *src,
|
86 | 90 | glDirectDrawSurface7 *dest, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx);
|
87 | 91 | GLuint MakeTexture(GLint min, GLint mag, GLint wraps, GLint wrapt, DWORD width, DWORD height, GLint texformat1, GLint texformat2, GLint texformat3);
|
— | — | @@ -88,8 +92,12 @@ |
89 | 93 | void DeleteTexture(GLuint texture);
|
90 | 94 | void InitD3D(int zbuffer);
|
91 | 95 | void Flush();
|
| 96 | + void SetRenderState(DWORD index, DWORD count, DWORD *data);
|
| 97 | + void SetMatrix(DWORD index, DWORD count, D3DMATRIX *data);
|
| 98 | + void Sync(int size);
|
| 99 | + int AddQueue(DWORD opcode, int mode, DWORD size, int paramcount, ...);
|
92 | 100 | HRESULT Clear(glDirectDrawSurface7 *target, DWORD dwCount, LPD3DRECT lpRects, DWORD dwFlags, DWORD dwColor, D3DVALUE dvZ, DWORD dwStencil);
|
93 | | - HRESULT DrawPrimitives(glDirect3DDevice7 *device, GLenum mode, GLVERTEX *vertices, int *texformats, DWORD count, LPWORD indices,
|
| 101 | + HRESULT DrawPrimitives(glDirect3DDevice7 *device, GLenum mode, GLVERTEX *vertices, bool packed, DWORD *texformats, DWORD count, LPWORD indices,
|
94 | 102 | DWORD indexcount, DWORD flags);
|
95 | 103 | HGLRC hRC;
|
96 | 104 | LRESULT WndProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam);
|
— | — | @@ -98,9 +106,9 @@ |
99 | 107 | // In-thread APIs
|
100 | 108 | DWORD _Entry();
|
101 | 109 | BOOL _InitGL(int width, int height, int bpp, int fullscreen, HWND hWnd, glDirectDraw7 *glDD7);
|
102 | | - int _UploadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2, int texformat3);
|
103 | | - int _DownloadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2);
|
104 | | - HRESULT _Blt(LPRECT lpDestRect, glDirectDrawSurface7 *src,
|
| 110 | + void _UploadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2, int texformat3);
|
| 111 | + void _DownloadTexture(char *buffer, char *bigbuffer, GLuint texture, int x, int y, int bigx, int bigy, int pitch, int bigpitch, int bpp, int texformat, int texformat2);
|
| 112 | + void _Blt(LPRECT lpDestRect, glDirectDrawSurface7 *src,
|
105 | 113 | glDirectDrawSurface7 *dest, LPRECT lpSrcRect, DWORD dwFlags, LPDDBLTFX lpDDBltFx);
|
106 | 114 | GLuint _MakeTexture(GLint min, GLint mag, GLint wraps, GLint wrapt, DWORD width, DWORD height, GLint texformat1, GLint texformat2, GLint texformat3);
|
107 | 115 | void _DrawScreen(GLuint texture, GLuint paltex, glDirectDrawSurface7 *dest, glDirectDrawSurface7 *src);
|
— | — | @@ -108,14 +116,16 @@ |
109 | 117 | void _DrawBackbuffer(GLuint *texture, int x, int y);
|
110 | 118 | void _InitD3D(int zbuffer);
|
111 | 119 | void _Clear(glDirectDrawSurface7 *target, DWORD dwCount, LPD3DRECT lpRects, DWORD dwFlags, DWORD dwColor, D3DVALUE dvZ, DWORD dwStencil);
|
112 | | - void glRenderer::_DrawPrimitives(glDirect3DDevice7 *device, GLenum mode, GLVERTEX *vertices, int *texcormats, DWORD count, LPWORD indices,
|
| 120 | + void _DrawPrimitives(glDirect3DDevice7 *device, GLenum mode, GLVERTEX *vertices, int *texcormats, DWORD count, LPWORD indices,
|
113 | 121 | DWORD indexcount, DWORD flags);
|
| 122 | + void _SetRenderState(DWORD index, DWORD count, DWORD *data);
|
| 123 | + void _SetMatrix(DWORD index, DWORD count, D3DMATRIX *data);
|
| 124 | + void _UpdateNormalMatrix();
|
114 | 125 | glDirectDraw7 *ddInterface;
|
115 | 126 | void _Flush();
|
116 | | - void* inputs[32];
|
117 | | - void* outputs[32];
|
| 127 | + void* inputs[7];
|
| 128 | + void* output;
|
118 | 129 | HANDLE hThread;
|
119 | | - bool wndbusy;
|
120 | 130 | HDC hDC;
|
121 | 131 | HWND hWnd;
|
122 | 132 | HWND hRenderWnd;
|
— | — | @@ -122,7 +132,22 @@ |
123 | 133 | bool hasHWnd;
|
124 | 134 | DIB dib;
|
125 | 135 | GLuint PBO;
|
126 | | - CRITICAL_SECTION cs;
|
| 136 | + HANDLE busy;
|
| 137 | + HANDLE start;
|
| 138 | + HANDLE sync;
|
| 139 | + bool running;
|
| 140 | + CRITICAL_SECTION commandcs;
|
| 141 | + CRITICAL_SECTION queuecs;
|
| 142 | + LPDWORD queue;
|
| 143 | + int queuesize;
|
| 144 | + int queuelength;
|
| 145 | + int queue_read;
|
| 146 | + int queue_write;
|
| 147 | + int syncsize;
|
| 148 | + bool dead;
|
| 149 | + DWORD renderstate[153];
|
| 150 | + D3DMATRIX matrices[24];
|
| 151 | + bool normal_dirty;
|
127 | 152 | };
|
128 | 153 |
|
129 | 154 | #endif //_GLRENDERER_H |
\ No newline at end of file |