1 /* Emacs style mode select -*- C++ -*-
2 *-----------------------------------------------------------------------------
3 *
4 *
5 * PrBoom: a Doom port merged with LxDoom and LSDLDoom
6 * based on BOOM, a modified and improved DOOM engine
7 * Copyright (C) 1999 by
8 * id Software, Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman
9 * Copyright (C) 1999-2000 by
10 * Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze
11 * Copyright 2005, 2006 by
12 * Florian Schulze, Colin Phipps, Neil Stevens, Andrey Budko
13 *
14 * This program is free software; you can redistribute it and/or
15 * modify it under the terms of the GNU General Public License
16 * as published by the Free Software Foundation; either version 2
17 * of the License, or (at your option) any later version.
18 *
19 * This program is distributed in the hope that it will be useful,
20 * but WITHOUT ANY WARRANTY; without even the implied warranty of
21 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
22 * GNU General Public License for more details.
23 *
24 * You should have received a copy of the GNU General Public License
25 * along with this program; if not, write to the Free Software
26 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
27 * 02111-1307, USA.
28 *
29 * DESCRIPTION:
30 * 2D-in-3D video code
31 *
32 *---------------------------------------------------------------------
33 */
34
35 #ifdef HAVE_CONFIG_H
36 #include "config.h"
37 #endif
38
39 #include "gl_opengl.h"
40
41 #include "gl_intern.h"
42 #include "gl_struct.h"
43 #include "i_video.h"
44 #include "e6y.h"
45
gld_Init8InGLMode(void)46 void gld_Init8InGLMode(void)
47 {
48 // clean up texture
49 if (vid_8ingl.texid)
50 {
51 glDeleteTextures(1, &vid_8ingl.texid);
52 vid_8ingl.texid = 0;
53 }
54
55 // clean up PBOs
56 if (vid_8ingl.pboids[0])
57 {
58 GLEXT_glDeleteBuffersARB(2, vid_8ingl.pboids);
59 memset(vid_8ingl.pboids, 0, sizeof(vid_8ingl.pboids));
60 }
61
62 // deallocate texture buffer
63 if (vid_8ingl.buf)
64 {
65 free(vid_8ingl.buf);
66 vid_8ingl.buf = NULL;
67 }
68
69 gld_InitOpenGL(gl_compatibility);
70 gld_InitTextureParams();
71 gld_EnableTexture2D(GL_TEXTURE0_ARB, true);
72 glPixelStorei(GL_UNPACK_ALIGNMENT, 1);
73 glViewport(0, 0, REAL_SCREENWIDTH, REAL_SCREENHEIGHT);
74 gld_Set2DMode();
75
76 vid_8ingl.width = gld_GetTexDimension(REAL_SCREENWIDTH);
77 vid_8ingl.height = gld_GetTexDimension(REAL_SCREENHEIGHT);
78 vid_8ingl.size = vid_8ingl.width * vid_8ingl.height * 4;
79
80 vid_8ingl.fU1 = 0.0f;
81 vid_8ingl.fU2 = (float)REAL_SCREENWIDTH / (float)vid_8ingl.width;
82 vid_8ingl.fV1 = 0.0f;
83 vid_8ingl.fV2 = (float)REAL_SCREENHEIGHT / (float)vid_8ingl.height;
84
85 glGenTextures(1, &vid_8ingl.texid);
86
87 glBindTexture(GL_TEXTURE_2D, vid_8ingl.texid);
88
89 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP);
90 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP);
91 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
92 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
93
94 glTexImage2D(GL_TEXTURE_2D, 0, gl_tex_format,
95 vid_8ingl.width, vid_8ingl.height,
96 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
97
98 glBindTexture(GL_TEXTURE_2D, 0);
99
100 // create 2 pixel buffer objects, you need to delete them when program exits.
101 // glBufferDataARB with NULL pointer reserves only memory space.
102 if (gl_arb_pixel_buffer_object)
103 {
104 GLEXT_glGenBuffersARB(2, vid_8ingl.pboids);
105 GLEXT_glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, vid_8ingl.pboids[0]);
106 GLEXT_glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, vid_8ingl.size, 0, GL_STREAM_DRAW_ARB);
107 GLEXT_glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, vid_8ingl.pboids[1]);
108 GLEXT_glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, vid_8ingl.size, 0, GL_STREAM_DRAW_ARB);
109 GLEXT_glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
110 }
111 else
112 {
113 vid_8ingl.buf = malloc(vid_8ingl.size);
114 }
115 }
116
UpdatePixels(unsigned char * dst)117 void UpdatePixels(unsigned char* dst)
118 {
119 int x, y;
120
121 unsigned int *pal = (unsigned int*)(vid_8ingl.colours +
122 256 * vid_8ingl.palette * 4);
123
124 if (V_GetMode() == VID_MODE8)
125 {
126 for (y = 0; y < REAL_SCREENHEIGHT; y++)
127 {
128 byte *px = (((byte*)vid_8ingl.screen->pixels) + y * vid_8ingl.screen->pitch);
129 int *py = ((int*)dst) + y * vid_8ingl.width;
130 for (x = 0; x < REAL_SCREENWIDTH; x++)
131 {
132 *(int*)py = pal[*(byte*)px];
133 px += 1;
134 py += 1;
135 }
136 }
137 } else if (V_GetMode() == VID_MODE15 || V_GetMode() == VID_MODE16)
138 {
139 unsigned int Rshift, Gshift, Bshift;
140 unsigned int Rmask, Gmask, Bmask;
141 SDL_PixelFormat *format = vid_8ingl.screen->format;
142
143 Rmask = format->Rmask;
144 Gmask = format->Gmask;
145 Bmask = format->Bmask;
146
147 Rshift = 16 - format->Rshift + format->Rloss;
148 Gshift = 8 - format->Gshift + format->Gloss;
149 Bshift = 0 - format->Bshift + format->Bloss;
150
151 for (y = 0; y < REAL_SCREENHEIGHT; y++)
152 {
153 byte *px = (((byte*)vid_8ingl.screen->pixels) + y * vid_8ingl.screen->pitch);
154 int *py = ((int*)dst) + y * vid_8ingl.width;
155 for (x = 0; x < REAL_SCREENWIDTH; x++)
156 {
157 short color = *(short*)px;
158 *(int*)py =
159 ((color & Bmask) << Bshift) |
160 ((color & Gmask) << Gshift) |
161 ((color & Rmask) << Rshift);
162 px += 2;
163 py += 1;
164 }
165 }
166 }
167 else if (V_GetMode() == VID_MODE32)
168 {
169 for (y = 0; y < REAL_SCREENHEIGHT; y++)
170 {
171 byte *px = (((byte*)vid_8ingl.screen->pixels) + y * vid_8ingl.screen->pitch);
172 int *py = ((int*)dst) + y * vid_8ingl.width;
173 for (x = 0; x < REAL_SCREENWIDTH; x++)
174 {
175 *(int*)py = *(int*)px;
176 px += 4;
177 py += 1;
178 }
179 }
180 }
181 }
182
gld_Draw8InGL(void)183 void gld_Draw8InGL(void)
184 {
185 if (gl_arb_pixel_buffer_object)
186 {
187 const int pboMode = 2;
188 unsigned char *ptr;
189 static int index = 0;
190 int nextIndex = 0; // pbo index used for next frame
191
192 // increment current index first then get the next index
193 // "index" is used to copy pixels from a PBO to a texture object
194 // "nextIndex" is used to update pixels in a PBO
195 index = (index + 1) % 2;
196 if (pboMode == 1) // with 1 PBO
197 nextIndex = index;
198 else if (pboMode == 2) // with 2 PBO
199 nextIndex = (index + 1) % 2;
200
201 // bind the texture and PBO
202 glBindTexture(GL_TEXTURE_2D, vid_8ingl.texid);
203 GLEXT_glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, vid_8ingl.pboids[index]);
204
205 // copy pixels from PBO to texture object
206 // Use offset instead of ponter.
207 #if 0
208 glTexImage2D(GL_TEXTURE_2D, 0, gl_tex_format,
209 vid_8ingl.width, vid_8ingl.height,
210 0, GL_BGRA, GL_UNSIGNED_BYTE, 0);
211 #else
212 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
213 vid_8ingl.width, vid_8ingl.height,
214 GL_BGRA, GL_UNSIGNED_BYTE, 0);
215 #endif
216
217 // bind PBO to update pixel values
218 GLEXT_glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, vid_8ingl.pboids[nextIndex]);
219
220 // map the buffer object into client's memory
221 // Note that glMapBufferARB() causes sync issue.
222 // If GPU is working with this buffer, glMapBufferARB() will wait(stall)
223 // for GPU to finish its job. To avoid waiting (stall), you can call
224 // first glBufferDataARB() with NULL pointer before glMapBufferARB().
225 // If you do that, the previous data in PBO will be discarded and
226 // glMapBufferARB() returns a new allocated pointer immediately
227 // even if GPU is still working with the previous data.
228 GLEXT_glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, vid_8ingl.size, 0, GL_STREAM_DRAW_ARB);
229
230 ptr = GLEXT_glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
231 if (ptr)
232 {
233 // update data directly on the mapped buffer
234 UpdatePixels(ptr);
235
236 // release pointer to mapping buffer
237 GLEXT_glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB);
238 }
239
240 // it is good idea to release PBOs with ID 0 after use.
241 // Once bound with 0, all pixel operations behave normal ways.
242 GLEXT_glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
243 }
244 else
245 {
246 glBindTexture(GL_TEXTURE_2D, vid_8ingl.texid);
247
248 UpdatePixels(vid_8ingl.buf);
249
250 #if 0
251 glTexImage2D(GL_TEXTURE_2D, 0, gl_tex_format,
252 vid_8ingl.width, vid_8ingl.height,
253 0, GL_BGRA, GL_UNSIGNED_BYTE, vid_8ingl.buf);
254 #else
255 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0,
256 vid_8ingl.width, vid_8ingl.height,
257 GL_BGRA, GL_UNSIGNED_BYTE, vid_8ingl.buf);
258 #endif
259 }
260
261 glBegin(GL_TRIANGLE_STRIP);
262 {
263 glTexCoord2f(vid_8ingl.fU1, vid_8ingl.fV1);
264 glVertex2f(0.0f, 0.0f);
265
266 glTexCoord2f(vid_8ingl.fU1, vid_8ingl.fV2);
267 glVertex2f(0.0f, (float)REAL_SCREENHEIGHT);
268
269 glTexCoord2f(vid_8ingl.fU2, vid_8ingl.fV1);
270 glVertex2f((float)REAL_SCREENWIDTH, 0.0f);
271
272 glTexCoord2f(vid_8ingl.fU2, vid_8ingl.fV2);
273 glVertex2f((float)REAL_SCREENWIDTH, (float)REAL_SCREENHEIGHT);
274 }
275 glEnd();
276
277 // unbind texture
278 glBindTexture(GL_TEXTURE_2D, 0);
279
280 glFinish();
281 SDL_GL_SwapBuffers();
282 }
283