view src/win32/OpenGL.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
line wrap: on
line source
1 #include "stdafx.h"
2 #include <gl/GL.h>
4 #include "resource.h"
5 #include "MainWnd.h"
6 #include "Reg.h"
7 #include "VBA.h"
9 #include "../gba/GBAGlobals.h"
10 #include "../gb/gbGlobals.h"
11 #include "../common/Text.h"
12 #include "../version.h"
14 #ifdef MMX
15 extern "C" bool cpu_mmx;
17 extern bool detectMMX();
18 #endif
20 extern int systemSpeed;
21 extern int Init_2xSaI(u32);
22 extern void winlog(const char *, ...);
24 class OpenGLDisplay : public IDisplay
25 {
26 private:
27 HDC hDC;
28 HGLRC hglrc;
29 GLuint texture;
30 int width;
31 int height;
32 float size;
33 u8 * filterData;
34 bool failed;
36 bool initializeTexture(int w, int h);
37 void updateFiltering(int);
38 public:
39 OpenGLDisplay();
40 virtual ~OpenGLDisplay();
42 virtual bool initialize();
43 virtual void cleanup();
44 virtual void render();
45 virtual void checkFullScreen();
46 virtual void renderMenu();
47 virtual void clear();
48 virtual bool changeRenderSize(int w, int h);
49 virtual void resize(int w, int h);
50 virtual DISPLAY_TYPE getType() { return OPENGL; };
51 virtual void setOption(const char *, int);
52 virtual int selectFullScreenMode(GUID * *);
53 };
55 OpenGLDisplay::OpenGLDisplay()
56 {
57 hDC = NULL;
58 hglrc = NULL;
59 texture = 0;
60 width = 0;
61 height = 0;
62 size = 0.0f;
63 filterData = (u8 *)malloc(4*16*256*256); // sufficient for 4x filters @ 32bit color depth
64 failed = false;
65 }
67 OpenGLDisplay::~OpenGLDisplay()
68 {
69 cleanup();
70 }
72 void OpenGLDisplay::cleanup()
73 {
74 if (texture != 0)
75 {
76 glDeleteTextures(1, &texture);
77 texture = 0;
78 }
79 if (hglrc != NULL)
80 {
81 wglDeleteContext(hglrc);
82 wglMakeCurrent(NULL, NULL);
83 hglrc = NULL;
84 }
85 if (hDC != NULL)
86 {
87 ReleaseDC(*theApp.m_pMainWnd, hDC);
88 hDC = NULL;
89 }
90 if (filterData)
91 {
92 free(filterData);
93 filterData = NULL;
94 }
95 width = 0;
96 height = 0;
97 size = 0.0f;
98 }
100 bool OpenGLDisplay::initialize()
101 {
102 CWnd *pWnd = theApp.m_pMainWnd;
104 theApp.mode320Available = false;
105 theApp.mode640Available = false;
106 theApp.mode800Available = false;
108 CDC *dc = pWnd->GetDC();
109 HDC hDC = dc->GetSafeHdc();
111 PIXELFORMATDESCRIPTOR pfd = {
112 sizeof(PIXELFORMATDESCRIPTOR), // size of this pfd
113 1, // version number
114 PFD_DRAW_TO_WINDOW | // support window
115 PFD_SUPPORT_OPENGL | // support OpenGL
116 PFD_DOUBLEBUFFER, // double buffered
117 PFD_TYPE_RGBA, // RGBA type
118 16, // 16-bit color depth
119 0, 0, 0, 0, 0, 0, // color bits ignored
120 0, // no alpha buffer
121 0, // shift bit ignored
122 0, // no accumulation buffer
123 0, 0, 0, 0, // accum bits ignored
124 32, // 32-bit z-buffer
125 0, // no stencil buffer
126 0, // no auxiliary buffer
127 PFD_MAIN_PLANE, // main layer
128 0, // reserved
129 0, 0, 0 // layer masks ignored
130 };
131 int iPixelFormat;
133 if (!(iPixelFormat = ChoosePixelFormat(hDC, &pfd)))
134 {
135 winlog("Failed ChoosePixelFormat\n");
136 return false;
137 }
139 // obtain detailed information about
140 // the device context's first pixel format
141 if (!(DescribePixelFormat(hDC, iPixelFormat,
142 sizeof(PIXELFORMATDESCRIPTOR), &pfd)))
143 {
144 winlog("Failed DescribePixelFormat\n");
145 return false;
146 }
148 if (!SetPixelFormat(hDC, iPixelFormat, &pfd))
149 {
150 winlog("Failed SetPixelFormat\n");
151 return false;
152 }
154 if (!(hglrc = wglCreateContext(hDC)))
155 {
156 winlog("Failed wglCreateContext\n");
157 return false;
158 }
160 if (!wglMakeCurrent(hDC, hglrc))
161 {
162 winlog("Failed wglMakeCurrent\n");
163 return false;
164 }
165 pWnd->ReleaseDC(dc);
167 // setup 2D gl environment
168 glPushAttrib(GL_ENABLE_BIT);
169 glDisable(GL_DEPTH_TEST);
170 glDisable(GL_CULL_FACE);
171 glEnable(GL_TEXTURE_2D);
173 glViewport(0, 0, theApp.surfaceSizeX, theApp.surfaceSizeY);
175 glMatrixMode(GL_PROJECTION);
176 glLoadIdentity();
178 glOrtho(0.0, (GLdouble)(theApp.surfaceSizeX), (GLdouble)(theApp.surfaceSizeY),
179 0.0, 0.0, 1.0);
180 glMatrixMode(GL_MODELVIEW);
181 glLoadIdentity();
183 systemRedShift = 3;
184 systemGreenShift = 11;
185 systemBlueShift = 19;
186 systemColorDepth = 32;
187 theApp.fsColorDepth = 32;
189 Init_2xSaI(32);
190 #ifdef MMX
191 if (!theApp.disableMMX)
192 cpu_mmx = theApp.detectMMX();
193 else
194 cpu_mmx = 0;
195 #endif
197 if (theApp.ddrawDebug)
198 {
199 winlog("R shift: %d\n", systemRedShift);
200 winlog("G shift: %d\n", systemGreenShift);
201 winlog("B shift: %d\n", systemBlueShift);
202 }
204 switch (systemColorDepth)
205 {
206 case 16:
207 {
208 for (int i = 0; i < 0x10000; i++)
209 {
210 systemColorMap16[i] = ((i & 0x1f) << systemRedShift) |
211 (((i & 0x3e0) >> 5) << systemGreenShift) |
212 (((i & 0x7c00) >> 10) << systemBlueShift);
213 }
214 break;
215 }
216 case 24:
217 case 32:
218 {
219 for (int i = 0; i < 0x10000; i++)
220 {
221 systemColorMap32[i] = ((i & 0x1f) << systemRedShift) |
222 (((i & 0x3e0) >> 5) << systemGreenShift) |
223 (((i & 0x7c00) >> 10) << systemBlueShift);
224 }
225 break;
226 }
227 }
228 theApp.updateFilter();
229 theApp.updateIFB();
231 if (failed)
232 return false;
234 pWnd->DragAcceptFiles(TRUE);
236 return TRUE;
237 }
239 void OpenGLDisplay::clear()
240 {}
242 void OpenGLDisplay::renderMenu()
243 {
244 checkFullScreen();
245 if (theApp.m_pMainWnd)
246 theApp.m_pMainWnd->DrawMenuBar();
247 }
249 void OpenGLDisplay::checkFullScreen()
250 {
251 // if(tripleBuffering)
252 // pOpenGL->FlipToGDISurface();
253 }
255 void OpenGLDisplay::render()
256 {
257 void (*filterFunction)(u8 *, u32, u8 *, u8 *, u32, int, int) = theApp.filterFunction;
258 int filterWidth = theApp.filterWidth, filterHeight = theApp.filterHeight;
259 /*
260 if(textMethod == 1)
261 {
262 int copyX = 240, copyY = 160;
263 if(systemCartridgeType == 1)
264 if(gbBorderOn) copyX = 256, copyY = 224;
265 else copyX = 160, copyY = 144;
267 extern void Simple1x(u8*,u32,u8*,u8*,u32,int,int);
268 filterFunction = Simple1x;
269 filterWidth = copyX;
270 filterHeight = copyY;
271 }
272 */
273 int pitch = filterWidth * 4 + 4;
274 u8 *data = pix + (theApp.sizeX+1)*4;
276 int filterPitch = theApp.rect.right*4;
278 /*
279 // HACK: see below
280 if (textMethod == 1 && !filterFunction)
281 {
282 textMethod = 0; // must not be after systemMessage!
283 systemMessage(
284 0,
285 "The \"On Game\" text display mode does not work with this combination of renderers and filters.\nThe display mode is automatically being changed to \"In Game\" instead,\nbut this may cause message text to go into AVI recordings and screenshots.\nThis can be reconfigured by choosing \"Options->Video->Text Display Options...\"");
286 }
287 */
289 if (filterFunction)
290 {
291 data = filterData;
292 filterFunction(pix + pitch,
293 pitch,
294 (u8 *)theApp.delta,
295 (u8 *)filterData,
296 filterPitch,
297 filterWidth,
298 filterHeight);
299 }
301 if (theApp.showSpeed && theApp.videoOption > VIDEO_4X)
302 {
303 char buffer[30];
304 if (theApp.showSpeed == 1)
305 sprintf(buffer, "%3d%%", systemSpeed);
306 else
307 sprintf(buffer, "%3d%%(%d, %d fps)", systemSpeed,
308 systemFrameSkip,
309 theApp.showRenderedFrames);
311 if (filterFunction)
312 {
313 if (theApp.showSpeedTransparent)
314 drawTextTransp((u8 *)filterData,
315 filterPitch,
316 theApp.rect.left+10,
317 theApp.rect.bottom-10,
318 buffer);
319 else
320 drawText((u8 *)filterData,
321 filterPitch,
322 theApp.rect.left+10,
323 theApp.rect.bottom-10,
324 buffer);
325 }
326 else
327 {
328 if (theApp.showSpeedTransparent)
329 drawTextTransp((u8 *)pix,
330 pitch,
331 theApp.rect.left+10,
332 theApp.rect.bottom-10,
333 buffer);
334 else
335 drawText((u8 *)pix,
336 pitch,
337 theApp.rect.left+10,
338 theApp.rect.bottom-10,
339 buffer);
340 }
341 }
343 if (textMethod == 1 && filterFunction)
344 {
345 DrawTextMessages((u8 *)filterData, filterPitch, theApp.rect.left, theApp.rect.bottom);
346 }
348 // Texturemap complete texture to surface so we have free scaling
349 // and antialiasing
350 if (filterFunction)
351 {
352 glPixelStorei(GL_UNPACK_ROW_LENGTH, theApp.rect.right);
353 }
354 else
355 {
356 glPixelStorei(GL_UNPACK_ROW_LENGTH, theApp.sizeX+1);
357 }
359 glTexSubImage2D(GL_TEXTURE_2D, 0,
360 0, 0, theApp.rect.right, theApp.rect.bottom,
361 GL_RGBA, GL_UNSIGNED_BYTE, data);
363 if (theApp.glType == 0)
364 {
365 glBegin(GL_TRIANGLE_STRIP);
366 glTexCoord2f(0.0, 0.0); glVertex3i(0, 0, 0);
367 glTexCoord2f(theApp.rect.right/size, 0.0); glVertex3i(theApp.surfaceSizeX, 0, 0);
368 glTexCoord2f(0.0, theApp.rect.bottom/size); glVertex3i(0, theApp.surfaceSizeY, 0);
369 glTexCoord2f(theApp.rect.right/size, theApp.rect.bottom/size); glVertex3i(theApp.surfaceSizeX, theApp.surfaceSizeY, 0);
370 glEnd();
371 }
372 else
373 {
374 glBegin(GL_QUADS);
375 glTexCoord2f(0.0, 0.0); glVertex3i(0, 0, 0);
376 glTexCoord2f(theApp.rect.right/size, 0.0); glVertex3i(theApp.surfaceSizeX, 0, 0);
377 glTexCoord2f(theApp.rect.right/size, theApp.rect.bottom/size); glVertex3i(theApp.surfaceSizeX, theApp.surfaceSizeY, 0);
378 glTexCoord2f(0.0, theApp.rect.bottom/size); glVertex3i(0, theApp.surfaceSizeY, 0);
379 glEnd();
380 }
382 CDC *dc = theApp.m_pMainWnd->GetDC();
384 if (textMethod == 2 || (textMethod == 1 && !filterFunction)) // HACK: so that textMethod isn't changed
385 {
386 for (int slot = 0; slot < SCREEN_MESSAGE_SLOTS; slot++)
387 {
388 if (theApp.screenMessage[slot])
389 {
390 if ((theApp.screenMessageDuration[slot] < 0 ||
391 (int)(GetTickCount() - theApp.screenMessageTime[slot]) < theApp.screenMessageDuration[slot]) &&
392 (!theApp.disableStatusMessage || slot == 1 || slot == 2))
393 {
394 dc->SetBkMode(TRANSPARENT);
396 if (outlinedText)
397 {
398 dc->SetTextColor(textColor != 7 ? RGB(0, 0, 0) : RGB(255, 255, 255));
399 // draw black outline
400 const static int xd [8] = {-1, 0, 1, 1, 1, 0, -1, -1};
401 const static int yd [8] = {-1, -1, -1, 0, 1, 1, 1, 0};
402 for (int i = 0; i < 8; i++)
403 {
404 dc->TextOut(10+xd[i], theApp.surfaceSizeY - 20*(slot+1)+yd[i], theApp.screenMessageBuffer[slot]);
405 }
406 }
408 COLORREF color;
409 switch (textColor)
410 {
411 case 0:
412 color = RGB(255, 255, 255); break;
413 case 1:
414 color = RGB(255, 0, 0); break;
415 case 2:
416 color = RGB(255, 255, 0); break;
417 case 3:
418 color = RGB(0, 255, 0); break;
419 case 4:
420 color = RGB(0, 255, 255); break;
421 case 5:
422 color = RGB(0, 0, 255); break;
423 case 6:
424 color = RGB(255, 0, 255); break;
425 case 7:
426 color = RGB(0, 0, 0); break;
427 }
428 dc->SetTextColor(color);
430 // draw center text
431 dc->TextOut(10, theApp.surfaceSizeY - 20*(slot+1), theApp.screenMessageBuffer[slot]);
432 }
433 else
434 {
435 theApp.screenMessage[slot] = false;
436 }
437 }
438 }
439 }
441 SwapBuffers(dc->GetSafeHdc());
443 theApp.m_pMainWnd->ReleaseDC(dc);
444 }
446 void OpenGLDisplay::resize(int w, int h)
447 {
448 glViewport(0, 0, w, h);
449 glMatrixMode(GL_PROJECTION);
450 glLoadIdentity();
452 glOrtho(0.0, (GLdouble)(w), (GLdouble)(h), 0.0, 0.0, 1.0);
453 glMatrixMode(GL_MODELVIEW);
454 glLoadIdentity();
455 }
457 void OpenGLDisplay::updateFiltering(int value)
458 {
459 switch (value)
460 {
461 case 0:
462 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
463 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
464 break;
465 case 1:
466 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
467 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
468 break;
469 }
470 }
472 bool OpenGLDisplay::initializeTexture(int w, int h)
473 {
474 int mySize = 256;
475 size = 256.0f;
476 if (w > 511 || h > 511)
477 {
478 size = 1024.0f;
479 mySize = 1024;
480 }
481 else if (w > 255 || h > 255)
482 {
483 size = 512.0f;
484 mySize = 512;
485 }
486 glGenTextures(1, &texture);
487 glBindTexture(GL_TEXTURE_2D, texture);
489 int filter = regQueryDwordValue("glFilter", 0);
490 if (filter < 0 || filter > 1)
491 filter = 0;
492 updateFiltering(filter);
494 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, mySize, mySize, 0, GL_RGBA,
495 GL_UNSIGNED_BYTE, NULL);
496 width = w;
497 height = h;
499 return true;
500 }
502 bool OpenGLDisplay::changeRenderSize(int w, int h)
503 {
504 if (width != w || height != h)
505 {
506 if (texture != 0)
507 {
508 glDeleteTextures(1, &texture);
509 texture = 0;
510 }
511 if (!initializeTexture(w, h))
512 {
513 failed = true;
514 return false;
515 }
516 }
517 return true;
518 }
520 void OpenGLDisplay::setOption(const char *option, int value)
521 {
522 if (!strcmp(option, "glFilter"))
523 updateFiltering(value);
524 }
526 int OpenGLDisplay::selectFullScreenMode(GUID * *)
527 {
528 HWND wnd = GetDesktopWindow();
529 RECT r;
530 GetWindowRect(wnd, &r);
531 int w = (r.right - r.left) & 4095;
532 int h = (r.bottom - r.top) & 4095;
533 HDC dc = GetDC(wnd);
534 int c = GetDeviceCaps(dc, BITSPIXEL);
535 ReleaseDC(wnd, dc);
537 return (c << 24) | (w << 12) | h;
538 }
540 IDisplay *newOpenGLDisplay()
541 {
542 return new OpenGLDisplay();
543 }