WATCHMAKER: Implement "blitting" by keeping track of blits to the back buffer

This commit is contained in:
Einar Johan Trøan Sømåen 2022-11-06 21:39:06 +01:00 committed by Eugene Sandulenko
parent babafef502
commit 4457ede6f9
6 changed files with 124 additions and 84 deletions

View File

@ -156,6 +156,92 @@ bool gClipToBlitterViewport(int *sposx, int *sposy, int *sdimx, int *sdimy,
return true;
}
void enter2Dmode(WGame &game) {
glMatrixMode(GL_PROJECTION);
glPushMatrix();
glLoadIdentity();
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
glLoadIdentity();
checkGlError("Exiting enter2Dmode");
}
void exit2Dmode() {
glPopMatrix();
glMatrixMode(GL_PROJECTION);
glPopMatrix();
glMatrixMode(GL_MODELVIEW);
checkGlError("exit2Dmode");
}
void renderTexture(WGame &game, gTexture &bitmap, Rect srcRect, Rect dstRect) {
checkGlError("Entering renderTexture");
glClearColor(0,0,1,0);
glEnable(GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
glDisable(GL_DEPTH_TEST);
glDepthFunc(GL_ALWAYS);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
bitmap.texture->bind();
glLoadIdentity();
glTranslatef(0, 0, 0.0);
float bottomSrc = ((float)srcRect.bottom) / bitmap.RealDimY;
float topSrc = ((float)srcRect.top) / bitmap.RealDimY;
float leftSrc = ((float)srcRect.left) / bitmap.RealDimX;
float rightSrc = ((float)srcRect.right) / bitmap.RealDimX;
Rect viewport = game._renderer->_viewport;
float bottomDst = 1.0 - ((dstRect.bottom == 0 ? 0 : ((double)dstRect.bottom) / viewport.height()) * 2.0);
float topDst = 1.0 - ((dstRect.top == 0 ? 0 : ((double)dstRect.top) / viewport.height()) * 2.0);
float leftDst = ((dstRect.left == 0 ? 0 : ((double)dstRect.left) / viewport.width()) * 2.0) - 1.0;
float rightDst = ((dstRect.right == 0 ? 0 : ((double)dstRect.right) / viewport.width()) * 2.0) - 1.0;
glBegin(GL_QUADS);
glColor3f(1.0, 1.0, 1.0);
glTexCoord2f(leftSrc, bottomSrc); // Bottom Left
glVertex3f(leftDst, bottomDst, 0.0f);
glTexCoord2f(rightSrc, bottomSrc); // Bottom Right
glVertex3f(rightDst, bottomDst, 0.0f);
glTexCoord2f(rightSrc, topSrc); // Top Right
glVertex3f(rightDst, topDst, 0.0f);
glTexCoord2f(leftSrc, topSrc); // Top Left
glVertex3f(leftDst, topDst, 0.0f);
glEnd();
glFlush();
checkGlError("Exiting renderTexture");
}
void gTexture::render(WGame &game, Rect src, Rect dst) {
// Render self
if (texture) {
renderTexture(game, *this, src, dst);
}
for (int i = 0; i < _blitsOnTop.size(); i++) {
_blitsOnTop[i].texture->render(game, _blitsOnTop[i].src, _blitsOnTop[i].dst);
}
}
void rBlitScreenBuffer(WGame &game) { // Should probably go to opengl_2d
checkGlError("Entering rBlitScreenBuffer");
enter2Dmode(game);
gBitmapList[BACK_BUFFER].render(game, game._renderer->_viewport, game._renderer->_viewport);
exit2Dmode();
checkGlError("Exiting rBlitScreenBuffer");
}
void rClear(int dst, int dposx, int dposy, int sdimx, int sdimy, unsigned char r, unsigned char g, unsigned char b) {
warning("STUBBED: rClear(%d, %d, %d, %d, %d", dst, dposx, dposy, sdimx, sdimy);
gBitmapList[dst].clear();
}
//************************************************************************************************************************
void rBlitter(WGame &game, int dst, int src, int dposx, int dposy,
int sposx, int sposy, int sdimx, int sdimy) {
@ -163,6 +249,9 @@ void rBlitter(WGame &game, int dst, int src, int dposx, int dposy,
warning("TODO: Stubbed rBlitter(%s, %d, %d, %d, %d, %d, %d, %d, %d)", gBitmapList[src].name.c_str(), dst, src, dposx, dposy, sposx, sposy, sdimx, sdimy);
auto &bitmap = gBitmapList[src];
assert(dst == 0);
auto &dstBitmap = gBitmapList[dst];
checkGlError("rBlitter Start");
glEnable(GL_TEXTURE_2D);
@ -179,38 +268,19 @@ void rBlitter(WGame &game, int dst, int src, int dposx, int dposy,
}
if ((dposx >= dwWidth) || (dposy >= dwHeight) || (sposx >= dwWidth) || (sposy >= dwHeight) ||
((dposx + sdimx) <= 0) || ((dposy + sdimy) <= 0) || ((sposx + sdimx) <= 0) || ((sposy + sdimy) <= 0))
((dposx + sdimx) <= 0) || ((dposy + sdimy) <= 0) || ((sposx + sdimx) <= 0) || ((sposy + sdimy) <= 0)) {
return;
}
if (dst == 0) {
#if 0
if (!gClipToBlitterViewport(&sposx, &sposy, &sdimx, &sdimy, &dposx, &dposy)) {
// DebugLogFile("gClipToBlitterViewport report an error");
error("gClipToBlitterViewport report an error");
return;
}
d = gScreenBuffer.lpDDSurface;
#endif
rUpdateExtends(dposx, dposy, dposx + sdimx, dposy + sdimy);
#if 0
/* //Update extends
if (dposx<gBlitterExtends.left)
gBlitterExtends.left=dposx;
if (dposy<gBlitterExtends.top)
gBlitterExtends.top=dposy;
if ((dposx+sdimx)>gBlitterExtends.right)
gBlitterExtends.right=dposx+sdimx;
if ((dposy+sdimy)>gBlitterExtends.bottom)
gBlitterExtends.bottom=dposy+sdimy;*/
} else
d = gBitmapList[dst].lpDDSurface;
if (src == 0) {
DebugLogFile("rBlitter error: src is an invalid surface");
return;
} else
s = gBitmapList[src].lpDDSurface;
#endif
rUpdateExtends(dposx, dposy, dposx + sdimx, dposy + sdimy);
}
if ((sdimx == 0) && (sdimy == 0)) {
sdimx = gBitmapList[src].DimX;
sdimy = gBitmapList[src].DimY;
@ -237,47 +307,7 @@ void rBlitter(WGame &game, int dst, int src, int dposx, int dposy,
// DebugLogWindow("gBlitter: blit not needed: dimx:%d dimy:%d", ( sr.top-sr.bottom ),( sr.left-sr.right ));
return;
}
glClearColor(0,0,1,0);
glEnable(GL_TEXTURE_2D);
glEnable(GL_ALPHA_TEST);
glEnable(GL_BLEND);
glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
bitmap.texture->bind();
glLoadIdentity();
glTranslatef(0, 0, -1.0);
//glTranslatef((2.0 / dposx) - 1.0, (2.0 / dposy) - 1.0, 0.0f);
//glClear(GL_COLOR_BUFFER_BIT);
float bottomSrc = ((float)srcRect.bottom) / bitmap.RealDimY;
float topSrc = ((float)srcRect.top) / bitmap.RealDimY;
float leftSrc = ((float)srcRect.left) / bitmap.RealDimX;
float rightSrc = ((float)srcRect.right) / bitmap.RealDimX;
Rect viewport = game._renderer->_viewport;
float bottomDst = 1.0 - ((dstRect.bottom == 0 ? 0 : ((double)dstRect.bottom) / viewport.height()) * 2.0);
float topDst = 1.0 - ((dstRect.top == 0 ? 0 : ((double)dstRect.top) / viewport.height()) * 2.0);
float leftDst = ((dstRect.left == 0 ? 0 : ((double)dstRect.left) / viewport.width()) * 2.0) - 1.0;
float rightDst = ((dstRect.right == 0 ? 0 : ((double)dstRect.right) / viewport.width()) * 2.0) - 1.0;
glBegin(GL_QUADS);
glColor3f(1.0, 1.0, 1.0);
glTexCoord2f(leftSrc, bottomSrc); // Bottom Left
glVertex3f(leftDst, bottomDst, 0.0f);
glTexCoord2f(rightSrc, bottomSrc); // Bottom Right
glVertex3f(rightDst, bottomDst, 0.0f);
glTexCoord2f(rightSrc, topSrc); // Top Right
glVertex3f(rightDst, topDst, 0.0f);
glTexCoord2f(leftSrc, topSrc); // Top Left
glVertex3f(leftDst, topDst, 0.0f);
glEnd();
glFlush();
dstBitmap.blitInto(&bitmap, srcRect, dstRect);
}
checkGlError("rBlitter End");

View File

@ -601,10 +601,12 @@ public:
checkGlError("glCompressedTexImage");
} else {
glTexImage2D(GL_TEXTURE_2D, 0, texFormat, data.getWidth(), data.getHeight(), 0, GL_RGBA, GL_UNSIGNED_BYTE, data.getData());
checkGlError("glTexImage2D");
}
}
void bind() override {
glBindTexture(GL_TEXTURE_2D, _texId);
checkGlError("OpenGLTexture::bind");
};
};

View File

@ -22,14 +22,17 @@
#ifndef WATCHMAKER_TEXTURE_H
#define WATCHMAKER_TEXTURE_H
#include "common/array.h"
#include "common/str.h"
#include "common/textconsole.h"
#include "watchmaker/3d/dds_header.h"
#include "graphics/surface.h"
#include "watchmaker/rect.h"
#include "watchmaker/surface.h"
namespace Watchmaker {
class WGame;
// Texture structs
struct gTexture {
Common::String name;
@ -45,8 +48,21 @@ struct gTexture {
return texture == nullptr;
}
void clear() {
error("TODO: Clear texture");
// TODO: This will only work for the back-surface
warning("Clearing %d", _blitsOnTop.size());
_blitsOnTop.clear();
}
void render(WGame &game, Rect src, Rect dst);
void blitInto(gTexture *texture, Rect src, Rect dst) {
_blitsOnTop.push_back({texture, src, dst});
}
private:
struct Blit {
gTexture *texture;
Rect src;
Rect dst;
};
Common::Array<Blit> _blitsOnTop;
};
} // End of namespace Watchmaker

View File

@ -223,7 +223,7 @@ void Regen(WGame &game) {
// DebugLogWindow( "Aggiorna video %d,%d %d,%d", ext.x1, ext.y1, ext.x2-ext.x1, ext.y2-ext.y1 );
#endif
rUpdateExtends(ext.x1, ext.y1, ext.x2, ext.y2);
rBlitScreenBuffer();
rBlitScreenBuffer(game);
rResetExtends();
// 5 - Copy PaintRect to OldPaintRect

View File

@ -90,6 +90,7 @@ bool checkGlError(const char *when) {
}
bool rClearBuffers(char flags) {
checkGlError("Entering rClearBuffers");
bool clearStencil = rGetStencilBitDepth() != 0;
bool clearDepth = flags & rCLEARZBUFFER;
bool clearBack = flags & rCLEARBACKBUFFER;
@ -144,12 +145,12 @@ void rGetScreenInfos(unsigned int *width, unsigned int *height, unsigned int *bp
}
gTexture *gLoadTexture(char *TextName, unsigned int LoaderFlags) {
warning("STUBBED gLoadTexture");
error("STUBBED gLoadTexture");
return nullptr;
}
bool rGrabVideo(const char *path, char flags) {
warning("STUBBED: rGrabVideo");
error("STUBBED: rGrabVideo");
return true;
}
@ -159,7 +160,7 @@ void rReleaseAllBitmaps(unsigned int NotFlags) {
}
void rReleaseBitmap(int i) {
warning("STUBBED: rReleaseBitmap");
error("STUBBED: rReleaseBitmap");
return;
}
@ -169,35 +170,26 @@ void rReleaseAllTextures(unsigned int NotFlags) {
}
void rSetBitmapName(unsigned int id, const char *s) {
warning("STUBBED: rSetBitmapName");
error("STUBBED: rSetBitmapName");
return;
}
uint32 rGetMovieFrame(MaterialPtr mat) {
warning("STUBBED: rGetMovieFrame");
error("STUBBED: rGetMovieFrame");
return 0;
}
void rPrintText(const char *s, unsigned int dst, unsigned int src, unsigned short *FontTable, unsigned short x, unsigned short y) {
warning("STUBBED: rPrintText");
error("STUBBED: rPrintText");
return;
}
void rGetTextDim(const char *s, unsigned short *FontTable, int *x, int *y) {
warning("STUBBED: rGetTextDim");
error("STUBBED: rGetTextDim");
return;
}
void rClear(int dst, int dposx, int dposy, int sdimx, int sdimy, unsigned char r, unsigned char g, unsigned char b) {
//warning("STUBBED: rClear(%d, %d, %d, %d, %d", dst, dposx, dposy, sdimx, sdimy);
}
void rBlitScreenBuffer(void) { // Should probably go to opengl_2d
//warning("STUBBED: rBlitScreenBuffer");
}
} // End of namespace Watchmaker
#endif // USE_OPENGL_GAME

View File

@ -211,7 +211,7 @@ int DebugQuick(signed int StdPx, signed int StdPy, const cha
bool rGetStencilBitDepth();
//Misc functions
void rBlitScreenBuffer();
void rBlitScreenBuffer(WGame &game);
void rPrintText(const char *s, unsigned int dst, unsigned int src, unsigned short *FontTable, unsigned short x, unsigned short y);
void rBlitter(WGame &game, int dst, int src, int dposx, int dposy, int sposx, int sposy, int sdimx, int sdimy);