18 GLPostProcessor::TextureData::TextureData()
22 GLPostProcessor::TextureData::TextureData(TextureData&& rhs)
23 : tex(std::move(rhs.tex))
24 , pbo(std::move(rhs.pbo))
32 unsigned maxWidth,
unsigned height_,
bool canDoInterlace)
34 videoSource, maxWidth, height_, canDoInterlace)
35 , noiseTextureA(256, 256)
36 , noiseTextureB(256, 256)
39 if (!GLEW_VERSION_2_0) {
41 "Your video card (or less likely video card driver) "
42 "doesn't support OpenGL 2.0. It's required for the "
43 "SDLGL-PP renderer.");
45 if (!glewIsSupported(
"GL_EXT_framebuffer_object")) {
47 "The OpenGL framebuffer object is not supported by "
48 "this glew library. Please upgrade your glew library.\n"
49 "It's also possible (but less likely) your video card "
50 "or video card driver doesn't support framebuffer "
62 for (
int i = 0; i < 2; ++i) {
66 glTexImage2D(GL_TEXTURE_2D,
78 monitor3DList = glGenLists(1);
90 glDeleteLists(monitor3DList, 1);
93 void GLPostProcessor::createRegions()
100 unsigned g =
Math::gcd(srcHeight, dstHeight);
101 unsigned srcStep = srcHeight / g;
102 unsigned dstStep = dstHeight / g;
106 unsigned srcStartY = 0;
107 unsigned dstStartY = 0;
108 while (dstStartY < dstHeight) {
111 assert(srcStartY < srcHeight);
115 unsigned srcEndY = srcStartY + srcStep;
116 unsigned dstEndY = dstStartY + dstStep;
117 while ((srcEndY < srcHeight) && (dstEndY < dstHeight) &&
123 regions.push_back(Region(srcStartY, srcEndY,
141 (horStretch != 320.0) ||
145 glClearColor(0.0f, 0.0f, 0.0f, 1.0f);
146 glClear(GL_COLOR_BUFFER_BIT);
155 if (scaleAlgorithm != algo) {
156 scaleAlgorithm = algo;
171 if (renderToTexture) {
173 glBindTexture(GL_TEXTURE_2D, 0);
174 fbo[frameCounter & 1].
push();
177 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
179 for (
auto& r : regions) {
182 assert(textures.find(r.lineWidth) != textures.end());
184 ? &superImposeTex :
nullptr;
185 currScaler->scaleImage(
186 textures[r.lineWidth].tex, superImpose,
187 r.srcStartY, r.srcEndY, r.lineWidth,
198 if (renderToTexture) {
199 fbo[frameCounter & 1].
pop();
200 colorTex[frameCounter & 1].
bind();
204 glEnable(GL_TEXTURE_2D);
206 glCallList(monitor3DList);
211 GLfloat x1 = (320.0f - GLfloat(horStretch)) / (2.0f * 320.0f);
212 GLfloat x2 = 1.0f - x1;
213 glTexCoord2f(x1, 0.0f); glVertex2i(0, h);
214 glTexCoord2f(x1, 1.0f); glVertex2i(0, 0);
215 glTexCoord2f(x2, 1.0f); glVertex2i(w, 0);
216 glTexCoord2f(x2, 0.0f); glVertex2i(w, h);
219 glDisable(GL_TEXTURE_2D);
230 std::unique_ptr<RawFrame> reuseFrame =
234 noiseX = double(rand()) / RAND_MAX;
235 noiseY = double(rand()) / RAND_MAX;
244 if (&setting == &noiseSetting) {
245 preCalcNoise(noiseSetting.
getValue());
246 }
else if (&setting == &horizontalStretch) {
247 preCalc3DDisplayList(horizontalStretch.
getValue());
251 void GLPostProcessor::uploadFrame()
256 for (
auto& r : regions) {
261 uploadBlock(std::max<int>(0, r.srcStartY - before),
262 std::min<int>(srcHeight, r.srcEndY + after),
269 if (superImposeTex.
getWidth() != width ||
271 superImposeTex.
resize(width, height);
274 superImposeTex.
bind();
288 void GLPostProcessor::uploadBlock(
289 unsigned srcStartY,
unsigned srcEndY,
unsigned lineWidth)
292 auto it = textures.find(lineWidth);
293 if (it == textures.end()) {
294 TextureData textureData;
296 textureData.tex = ColorTexture(
297 lineWidth, height * 2);
298 textureData.tex.setWrapMode(
false);
300 if (textureData.pbo.openGLSupported()) {
301 textureData.pbo.setImage(lineWidth, height * 2);
304 it = textures.insert(std::make_pair(
305 lineWidth, std::move(textureData))).first;
307 auto& tex = it->second.tex;
308 auto& pbo = it->second.pbo;
315 if (pbo.openGLSupported()) {
317 mapped = pbo.mapWrite();
322 for (
unsigned y = srcStartY; y < srcEndY; ++y) {
323 const unsigned* data =
326 mapped + y * lineWidth, data, lineWidth);
330 #if defined(__APPLE__)
334 if (lineWidth == 1 && srcStartY != 0 && srcStartY % 16 == 0) {
347 pbo.getOffset(0, srcStartY));
349 if (pbo.openGLSupported()) {
354 unsigned y = srcStartY;
355 unsigned remainingLines = srcEndY - srcStartY;
356 while (remainingLines) {
359 y, remainingLines, lines, lineWidth);
373 remainingLines -= lines;
375 glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
379 if (currScaler.get()) {
380 currScaler->uploadBlock(srcStartY, srcEndY, lineWidth, *
paintFrame);
384 void GLPostProcessor::drawGlow(
int glow)
386 if ((glow == 0) || !storedFrame)
return;
388 colorTex[(frameCounter & 1) ^ 1].bind();
389 glEnable(GL_TEXTURE_2D);
391 glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
393 GLfloat alpha = glow * 31 / 3200.0f;
394 glColor4f(0.0f, 0.0f, 0.0f, alpha);
397 glTexCoord2i(0, 0); glVertex2i(0, h);
398 glTexCoord2i(0, 1); glVertex2i(0, 0);
399 glTexCoord2i(1, 1); glVertex2i(w, 0);
400 glTexCoord2i(1, 0); glVertex2i(w, h);
403 glDisable(GL_TEXTURE_2D);
406 void GLPostProcessor::preCalcNoise(
double factor)
408 GLbyte buf1[256 * 256];
409 GLbyte buf2[256 * 256];
410 for (
int i = 0; i < 256 * 256; i += 2) {
414 buf1[i + 0] = (s1 > 0) ? s1 : 0;
415 buf2[i + 0] = (s1 < 0) ? -s1 : 0;
417 buf1[i + 1] = (s2 > 0) ? s2 : 0;
418 buf2[i + 1] = (s2 < 0) ? -s2 : 0;
424 void GLPostProcessor::drawNoise()
430 static const int coord[8][4][2] = {
431 { { 0, 0 }, { 320, 0 }, { 320, 240 }, { 0, 240 } },
432 { { 0, 240 }, { 320, 240 }, { 320, 0 }, { 0, 0 } },
433 { { 0, 240 }, { 0, 0 }, { 320, 0 }, { 320, 240 } },
434 { { 320, 240 }, { 320, 0 }, { 0, 0 }, { 0, 240 } },
435 { { 320, 240 }, { 0, 240 }, { 0, 0 }, { 320, 0 } },
436 { { 320, 0 }, { 0, 0 }, { 0, 240 }, { 320, 240 } },
437 { { 320, 0 }, { 320, 240 }, { 0, 240 }, { 0, 0 } },
438 { { 0, 0 }, { 0, 240 }, { 320, 240 }, { 320, 0 } }
442 unsigned seq = frameCounter & 7;
443 glPushAttrib(GL_ALL_ATTRIB_BITS);
445 glBlendFunc(GL_ONE, GL_ONE);
446 glEnable(GL_TEXTURE_2D);
447 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_REPLACE);
448 noiseTextureA.
bind();
450 glTexCoord2f(0.0f + GLfloat(noiseX), 1.875f + GLfloat(noiseY));
451 glVertex2i(coord[seq][0][0] * zoom, coord[seq][0][1] * zoom);
452 glTexCoord2f(2.5f + GLfloat(noiseX), 1.875f + GLfloat(noiseY));
453 glVertex2i(coord[seq][1][0] * zoom, coord[seq][1][1] * zoom);
454 glTexCoord2f(2.5f + GLfloat(noiseX), 0.000f + GLfloat(noiseY));
455 glVertex2i(coord[seq][2][0] * zoom, coord[seq][2][1] * zoom);
456 glTexCoord2f(0.0f + GLfloat(noiseX), 0.000f + GLfloat(noiseY));
457 glVertex2i(coord[seq][3][0] * zoom, coord[seq][3][1] * zoom);
462 if (glBlendEquation) glBlendEquation(GL_FUNC_REVERSE_SUBTRACT);
463 noiseTextureB.
bind();
465 glTexCoord2f(0.0f + GLfloat(noiseX), 1.875f + GLfloat(noiseY));
466 glVertex2i(coord[seq][0][0] * zoom, coord[seq][0][1] * zoom);
467 glTexCoord2f(2.5f + GLfloat(noiseX), 1.875f + GLfloat(noiseY));
468 glVertex2i(coord[seq][1][0] * zoom, coord[seq][1][1] * zoom);
469 glTexCoord2f(2.5f + GLfloat(noiseX), 0.000f + GLfloat(noiseY));
470 glVertex2i(coord[seq][2][0] * zoom, coord[seq][2][1] * zoom);
471 glTexCoord2f(0.0f + GLfloat(noiseX), 0.000f + GLfloat(noiseY));
472 glVertex2i(coord[seq][3][0] * zoom, coord[seq][3][1] * zoom);
475 if (glBlendEquation) glBlendEquation(GL_FUNC_ADD);
478 void GLPostProcessor::preCalc3DDisplayList(
double width)
481 static const int GRID_SIZE = 16;
486 } points[GRID_SIZE + 1][GRID_SIZE + 1];
487 const int GRID_SIZE2 = GRID_SIZE / 2;
488 GLfloat s = GLfloat(width) / 320.0f;
489 GLfloat b = (320.0f - GLfloat(width)) / (2.0f * 320.0f);
491 for (
int sx = 0; sx <= GRID_SIZE; ++sx) {
492 for (
int sy = 0; sy <= GRID_SIZE; ++sy) {
493 Point& p = points[sx][sy];
494 GLfloat x = GLfloat(sx - GRID_SIZE2) / GRID_SIZE2;
495 GLfloat y = GLfloat(sy - GRID_SIZE2) / GRID_SIZE2;
499 p.vz = (x * x + y * y) / -12.0f;
505 p.tx = (GLfloat(sx) / GRID_SIZE) * s + b;
506 p.ty = GLfloat(sy) / GRID_SIZE;
510 GLfloat LightDiffuse[]= { 1.2f, 1.2f, 1.2f, 1.2f };
511 glLightfv(GL_LIGHT0, GL_DIFFUSE, LightDiffuse);
513 glEnable(GL_NORMALIZE);
515 glNewList(monitor3DList, GL_COMPILE);
516 glEnable(GL_LIGHTING);
517 glMatrixMode(GL_PROJECTION);
520 glFrustum(-1, 1, -1, 1, 1, 10);
521 glMatrixMode(GL_MODELVIEW);
524 glTranslatef(0.0f, 0.4f, -2.0f);
525 glRotatef(-10.0f, 1.0f, 0.0f, 0.0f);
526 glScalef(2.2f, 2.2f, 2.2f);
527 glTexEnvi(GL_TEXTURE_ENV, GL_TEXTURE_ENV_MODE, GL_MODULATE);
528 for (
int y = 0; y < GRID_SIZE; ++y) {
529 glBegin(GL_TRIANGLE_STRIP);
530 for (
int x = 0; x < (GRID_SIZE + 1); ++x) {
531 Point& p1 = points[x][y + 0];
532 Point& p2 = points[x][y + 1];
533 glTexCoord2f(p1.tx, p1.ty);
534 glNormal3f (p1.nx, p1.ny, p1.nz);
535 glVertex3f (p1.vx, p1.vy, p1.vz);
536 glTexCoord2f(p2.tx, p2.ty);
537 glNormal3f (p2.nx, p2.ny, p2.nz);
538 glVertex3f (p2.vx, p2.vy, p2.vz);
542 glMatrixMode(GL_PROJECTION);
544 glMatrixMode(GL_MODELVIEW);
546 glDisable(GL_LIGHTING);