[Scummvm-git-logs] scummvm master -> 02294ee7175ac3e2b400569508a432c19ee2be13
aquadran
aquadran at gmail.com
Thu Nov 12 07:18:47 UTC 2020
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
bd37cd3012 TINYGL: Make gl_resizeImage* pixel-format-independent
f8c72b5967 TINYGL: Move texture resampling from create time to render time
6f8303c2e3 MYST3: Use TGL_UNSIGNED_SHORT_5_6_5 texture format in gfx_tinygl
02294ee717 GRAPHICS: Use memcpy when copying to same-format-no-alpha destination
Commit: bd37cd301206f042222513cb02b0ef64bc91b5f1
https://github.com/scummvm/scummvm/commit/bd37cd301206f042222513cb02b0ef64bc91b5f1
Author: Vincent Pelletier (plr.vincent at gmail.com)
Date: 2020-11-12T08:13:49+01:00
Commit Message:
TINYGL: Make gl_resizeImage* pixel-format-independent
Changed paths:
graphics/tinygl/image_util.cpp
graphics/tinygl/texture.cpp
graphics/tinygl/zgl.h
diff --git a/graphics/tinygl/image_util.cpp b/graphics/tinygl/image_util.cpp
index 2bd9010ca4..7b20e30a4b 100644
--- a/graphics/tinygl/image_util.cpp
+++ b/graphics/tinygl/image_util.cpp
@@ -41,15 +41,16 @@ static inline int interpolate(int v00, int v01, int v10, int xf, int yf) {
// TODO: more accurate resampling
-void gl_resizeImage(unsigned char *dest, int xsize_dest, int ysize_dest,
- unsigned char *src, int xsize_src, int ysize_src) {
- unsigned char *pix, *pix_src;
- int point1_offset = 0, point2_offset = 0, point3_offset = 0;
+void gl_resizeImage(Graphics::PixelBuffer &dest, int xsize_dest, int ysize_dest,
+ const Graphics::PixelBuffer &src, int xsize_src, int ysize_src) {
+ int point1_offset, point2_offset, point3_offset, dest_offset = 0;
+ int point_y_offset, point_offset;
float x1, y1, x1inc, y1inc;
- int xi, yi, xf, yf;
-
- pix = dest;
- pix_src = src;
+ int xi, yi, xf, yf, curr_yf;
+ bool space_below, space_right;
+ uint8 r00, g00, b00, a00;
+ uint8 r01, g01, b01, a01;
+ uint8 r10, g10, b10, a10;
x1inc = (float)(xsize_src - 1) / (float)(xsize_dest - 1);
y1inc = (float)(ysize_src - 1) / (float)(ysize_dest - 1);
@@ -57,55 +58,49 @@ void gl_resizeImage(unsigned char *dest, int xsize_dest, int ysize_dest,
y1 = 0;
for (int y = 0; y < ysize_dest; y++) {
x1 = 0;
+ yi = (int)floorf(y1);
+ yf = (int)((y1 - yi) * INTERP_NORM);
+ point_y_offset = yi * xsize_src;
+ space_below = (yi + 1) < ysize_src;
for (int x = 0; x < xsize_dest; x++) {
- xi = (int)x1;
- yi = (int)y1;
- xf = (int)((x1 - floor(x1)) * INTERP_NORM);
- yf = (int)((y1 - floor(y1)) * INTERP_NORM);
-
+ xi = (int)floorf(x1);
+ xf = (int)((x1 - xi) * INTERP_NORM);
+ point1_offset = point_offset = point_y_offset + xi;
+ space_right = (xi + 1) < xsize_src;
if ((xf + yf) <= INTERP_NORM) {
- for (int j = 0; j < 3; j++) {
- point1_offset = (yi * xsize_src + xi) * 4 + j;
- if ((xi + 1) < xsize_src)
- point2_offset = (yi * xsize_src + xi + 1) * 4 + j;
- else
- point2_offset = point1_offset;
- if ((yi + 1) < ysize_src)
- point3_offset = ((yi + 1) * xsize_src + xi) * 4 + j;
- else
- point3_offset = point1_offset;
- pix[j] = interpolate(pix_src[point1_offset], pix_src[point2_offset], pix_src[point3_offset], xf, yf);
- }
- pix[3] = pix_src[(yi * xsize_src + xi) * 4 + 3];
+ curr_yf = yf;
+ if (space_right)
+ point2_offset = point_offset + 1;
+ else
+ point2_offset = point_offset;
+ if (space_below)
+ point3_offset = point_offset + xsize_src;
+ else
+ point3_offset = point_offset;
} else {
xf = INTERP_NORM - xf;
- yf = INTERP_NORM - yf;
- for (int j = 0; j < 3; j++) {
- pix[j] = interpolate(pix_src[point1_offset], pix_src[point2_offset], pix_src[point3_offset], xf, yf);
- if ((xi + 1) < xsize_src) {
- if ((yi + 1) < ysize_src)
- point1_offset = ((yi + 1) * xsize_src + xi + 1) * 4 + j;
- else
- point1_offset = (yi * xsize_src + xi + 1) * 4 + j;
- } else {
- if ((yi + 1) < ysize_src)
- point1_offset = ((yi + 1) * xsize_src + xi) * 4 + j;
- else
- point1_offset = (yi * xsize_src + xi) * 4 + j;
- }
- if ((yi + 1) < ysize_src)
- point2_offset = ((yi + 1) * xsize_src + xi) * 4 + j;
- else
- point2_offset = (yi * xsize_src + xi) * 4 + j;
- if ((xi + 1) < xsize_src)
- point3_offset = (yi * xsize_src + xi + 1) * 4 + j;
- else
- point3_offset = (yi * xsize_src + xi) * 4 + j;
- pix[j] = interpolate(pix_src[point1_offset], pix_src[point2_offset], pix_src[point3_offset], xf, yf);
- }
- pix[3] = pix_src[(yi * xsize_src + xi) * 4 + 3];
+ curr_yf = INTERP_NORM - yf;
+ if (space_right) {
+ point1_offset += 1;
+ point3_offset = point_offset + 1;
+ } else
+ point3_offset = point_offset;
+ if (space_below) {
+ point1_offset += xsize_src;
+ point2_offset = point_offset + xsize_src;
+ } else
+ point2_offset = point_offset;
}
- pix += 4;
+ src.getARGBAt(point1_offset, r00, g00, b00, a00);
+ src.getARGBAt(point2_offset, r01, g01, b01, a01);
+ src.getARGBAt(point3_offset, r10, g10, b10, a10);
+ dest.setPixelAt(
+ dest_offset++,
+ interpolate(r00, r01, r10, xf, curr_yf),
+ interpolate(g00, g01, g10, xf, curr_yf),
+ interpolate(b00, b01, b10, xf, curr_yf),
+ interpolate(a00, a01, a10, xf, curr_yf)
+ );
x1 += x1inc;
}
y1 += y1inc;
@@ -115,32 +110,23 @@ void gl_resizeImage(unsigned char *dest, int xsize_dest, int ysize_dest,
#define FRAC_BITS 16
// resizing with no interlating nor nearest pixel
-void gl_resizeImageNoInterpolate(unsigned char *dest, int xsize_dest, int ysize_dest,
- unsigned char *src, int xsize_src, int ysize_src) {
- unsigned char *pix, *pix_src, *pix1;
+void gl_resizeImageNoInterpolate(Graphics::PixelBuffer &dest, int xsize_dest, int ysize_dest,
+ const Graphics::PixelBuffer &src, int xsize_src, int ysize_src) {
+ int dest_offset = 0;
int x1, y1, x1inc, y1inc;
- int xi, yi;
-
- pix = dest;
- pix_src = src;
+ int yi;
+ uint8 r, g, b, a;
x1inc = (int)((float)((xsize_src) << FRAC_BITS) / (float)(xsize_dest));
y1inc = (int)((float)((ysize_src) << FRAC_BITS) / (float)(ysize_dest));
y1 = 0;
for (int y = 0; y < ysize_dest; y++) {
+ yi = (y1 >> FRAC_BITS) * xsize_src;
x1 = 0;
for (int x = 0; x < xsize_dest; x++) {
- xi = x1 >> FRAC_BITS;
- yi = y1 >> FRAC_BITS;
- pix1 = pix_src + (yi * xsize_src + xi) * 4;
-
- pix[0] = pix1[0];
- pix[1] = pix1[1];
- pix[2] = pix1[2];
- pix[3] = pix1[3];
-
- pix += 4;
+ src.getARGBAt(yi + (x1 >> FRAC_BITS), r, g, b, a);
+ dest.setPixelAt(dest_offset++, r, g, b, a);
x1 += x1inc;
}
y1 += y1inc;
diff --git a/graphics/tinygl/texture.cpp b/graphics/tinygl/texture.cpp
index 18fbbcc21c..dd3dee16c3 100644
--- a/graphics/tinygl/texture.cpp
+++ b/graphics/tinygl/texture.cpp
@@ -211,16 +211,10 @@ void glopTexImage2D(GLContext *c, GLParam *p) {
if (pixels != NULL) {
Graphics::PixelBuffer src(formatType2PixelFormat(format, type), pixels);
if (width != c->_textureSize || height != c->_textureSize) {
- Graphics::PixelBuffer src_conv(pf, width * height, DisposeAfterUse::YES);
- src_conv.copyBuffer(
- 0,
- width * height,
- src
- );
// we use interpolation for better looking result
gl_resizeImage(
- internal.getRawBuffer(), c->_textureSize, c->_textureSize,
- src_conv.getRawBuffer(), width, height
+ internal, c->_textureSize, c->_textureSize,
+ src, width, height
);
} else {
internal.copyBuffer(
diff --git a/graphics/tinygl/zgl.h b/graphics/tinygl/zgl.h
index b19b14d5bf..0711a43386 100644
--- a/graphics/tinygl/zgl.h
+++ b/graphics/tinygl/zgl.h
@@ -423,10 +423,10 @@ void free_texture(GLContext *c, int h);
void free_texture(GLContext *c, GLTexture *t);
// image_util.c
-void gl_resizeImage(unsigned char *dest, int xsize_dest, int ysize_dest,
- unsigned char *src, int xsize_src, int ysize_src);
-void gl_resizeImageNoInterpolate(unsigned char *dest, int xsize_dest, int ysize_dest,
- unsigned char *src, int xsize_src, int ysize_src);
+void gl_resizeImage(Graphics::PixelBuffer &dest, int xsize_dest, int ysize_dest,
+ const Graphics::PixelBuffer &src, int xsize_src, int ysize_src);
+void gl_resizeImageNoInterpolate(Graphics::PixelBuffer &dest, int xsize_dest, int ysize_dest,
+ const Graphics::PixelBuffer &src, int xsize_src, int ysize_src);
void tglIssueDrawCall(Graphics::DrawCall *drawCall);
Commit: f8c72b5967f8fdfa6f2a15e7141b4f7bb94496a5
https://github.com/scummvm/scummvm/commit/f8c72b5967f8fdfa6f2a15e7141b4f7bb94496a5
Author: Vincent Pelletier (plr.vincent at gmail.com)
Date: 2020-11-12T08:15:39+01:00
Commit Message:
TINYGL: Move texture resampling from create time to render time
Thanks to pixel repacking using cpu data cache, this has a low runtime
cost even for TGL_LINEAR.
Adds support for TGL_NEAREST.
Adds support for TGL_MIRRORED_REPEAT, TGL_CLAMP_TO_EDGE and TGL_REPEAT.
Also, add support for more texture clamping and resampling options.
Mipmaps are not supported, although their sampling modes will be
applied - but to the full-size texture instead of selected mipmap.
Note: Texture sampler is still chosen at texture creation time.
Changed paths:
A graphics/tinygl/texelbuffer.cpp
A graphics/tinygl/texelbuffer.h
graphics/module.mk
graphics/tinygl/clip.cpp
graphics/tinygl/gl.h
graphics/tinygl/texture.cpp
graphics/tinygl/zbuffer.cpp
graphics/tinygl/zbuffer.h
graphics/tinygl/zdirtyrect.cpp
graphics/tinygl/zdirtyrect.h
graphics/tinygl/zgl.h
graphics/tinygl/ztriangle.cpp
diff --git a/graphics/module.mk b/graphics/module.mk
index 8bcff4a94e..0c367008dc 100644
--- a/graphics/module.mk
+++ b/graphics/module.mk
@@ -71,6 +71,7 @@ MODULE_OBJS += \
tinygl/select.o \
tinygl/specbuf.o \
tinygl/texture.o \
+ tinygl/texelbuffer.o \
tinygl/vertex.o \
tinygl/zbuffer.o \
tinygl/zline.o \
diff --git a/graphics/tinygl/clip.cpp b/graphics/tinygl/clip.cpp
index 244210929d..b6b6f3469e 100644
--- a/graphics/tinygl/clip.cpp
+++ b/graphics/tinygl/clip.cpp
@@ -411,7 +411,7 @@ void gl_draw_triangle_fill(GLContext *c, GLVertex *p0, GLVertex *p1, GLVertex *p
#ifdef TINYGL_PROFILE
count_triangles_textured++;
#endif
- c->fb->setTexture(c->current_texture->images[0].pixmap);
+ c->fb->setTexture(c->current_texture->images[0].pixmap, c->texture_wrap_s, c->texture_wrap_t);
if (c->current_shade_model == TGL_SMOOTH) {
c->fb->fillTriangleTextureMappingPerspectiveSmooth(&p0->zp, &p1->zp, &p2->zp);
} else {
diff --git a/graphics/tinygl/gl.h b/graphics/tinygl/gl.h
index c7eb3aca0f..1a4a410d28 100644
--- a/graphics/tinygl/gl.h
+++ b/graphics/tinygl/gl.h
@@ -537,6 +537,8 @@ enum {
TGL_NEAREST = 0x2600,
TGL_REPEAT = 0x2901,
TGL_CLAMP = 0x2900,
+ TGL_CLAMP_TO_EDGE = 0x812F,
+ TGL_MIRRORED_REPEAT = 0x8370,
TGL_S = 0x2000,
TGL_T = 0x2001,
TGL_R = 0x2002,
diff --git a/graphics/tinygl/texelbuffer.cpp b/graphics/tinygl/texelbuffer.cpp
new file mode 100644
index 0000000000..d14bcf9fe0
--- /dev/null
+++ b/graphics/tinygl/texelbuffer.cpp
@@ -0,0 +1,225 @@
+/* ResidualVM - A 3D game interpreter
+ *
+ * ResidualVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "graphics/tinygl/gl.h"
+#include "graphics/tinygl/zgl.h"
+#include "graphics/tinygl/zbuffer.h"
+#include "graphics/tinygl/texelbuffer.h"
+
+namespace Graphics {
+
+#define ZB_POINT_ST_UNIT (1 << ZB_POINT_ST_FRAC_BITS)
+#define ZB_POINT_ST_FRAC_MASK (ZB_POINT_ST_UNIT - 1)
+
+TexelBuffer::TexelBuffer(unsigned int width, unsigned int height, unsigned int textureSize) {
+ assert(width);
+ assert(height);
+ assert(textureSize);
+
+ _width = width;
+ _height = height;
+ _fracTextureUnit = textureSize << ZB_POINT_ST_FRAC_BITS;
+ _fracTextureMask = _fracTextureUnit - 1;
+ _widthRatio = (float) width / textureSize;
+ _heightRatio = (float) height / textureSize;
+}
+
+static inline unsigned int wrap(unsigned int wrap_mode, int coord, unsigned int _fracTextureUnit, unsigned int _fracTextureMask) {
+ switch (wrap_mode) {
+ case TGL_MIRRORED_REPEAT:
+ if (coord & _fracTextureUnit)
+ return _fracTextureMask - (coord & _fracTextureMask);
+ return coord & _fracTextureMask;
+ case TGL_CLAMP_TO_EDGE:
+ if (coord < 0)
+ return 0;
+ if ((unsigned int) coord > _fracTextureMask)
+ return _fracTextureMask;
+ return coord;
+ default:
+ // Fall through
+ case TGL_REPEAT:
+ return coord & _fracTextureMask;
+ }
+}
+
+void TexelBuffer::getARGBAt(
+ unsigned int wrap_s, unsigned int wrap_t,
+ int s, int t,
+ uint8 &a, uint8 &r, uint8 &g, uint8 &b
+) const {
+ unsigned int x, y;
+ x = wrap(wrap_s, s, _fracTextureUnit, _fracTextureMask) * _widthRatio;
+ y = wrap(wrap_t, t, _fracTextureUnit, _fracTextureMask) * _heightRatio;
+ getARGBAt(
+ (x >> ZB_POINT_ST_FRAC_BITS) + (y >> ZB_POINT_ST_FRAC_BITS) * _width,
+ x & ZB_POINT_ST_FRAC_MASK, y & ZB_POINT_ST_FRAC_MASK,
+ a, r, g, b
+ );
+}
+
+// Nearest: store texture in original size.
+NearestTexelBuffer::NearestTexelBuffer(const PixelBuffer &buf, unsigned int width, unsigned int height, unsigned int textureSize) : TexelBuffer(width, height, textureSize) {
+ unsigned int pixel_count = _width * _height;
+ _buf = PixelBuffer(buf.getFormat(), pixel_count, DisposeAfterUse::NO);
+ _buf.copyBuffer(0, pixel_count, buf);
+}
+
+NearestTexelBuffer::~NearestTexelBuffer() {
+ _buf.free();
+}
+
+void NearestTexelBuffer::getARGBAt(
+ unsigned int pixel,
+ unsigned int, unsigned int,
+ uint8 &a, uint8 &r, uint8 &g, uint8 &b
+) const {
+ _buf.getARGBAt(pixel, a, r, g, b);
+}
+
+// Bilinear: each texture coordinates corresponds to the 4 original image
+// pixels linear interpolation has to work on, so that they are near each
+// other in CPU data cache, and a single actual memory fetch happens. This
+// allows applying linear filtering at render time at a very low performance
+// cost. As we expect to work on small-ish textures (512*512 ?) the 4x memory
+// usage increase should be negligible.
+#define A_OFFSET (0 * 4)
+#define R_OFFSET (1 * 4)
+#define G_OFFSET (2 * 4)
+#define B_OFFSET (3 * 4)
+#define P00_OFFSET 0
+#define P01_OFFSET 1
+#define P10_OFFSET 2
+#define P11_OFFSET 3
+#define PIXEL_PER_TEXEL_SHIFT 2
+
+BilinearTexelBuffer::BilinearTexelBuffer(const PixelBuffer &buf, unsigned int width, unsigned int height, unsigned int textureSize) : TexelBuffer(width, height, textureSize) {
+ unsigned int pixel00_offset = 0, pixel11_offset, pixel01_offset, pixel10_offset;
+ uint8 *texel8;
+ uint32 *texel32;
+
+ texel32 = _texels = new uint32[_width * _height << PIXEL_PER_TEXEL_SHIFT];
+ for (unsigned int y = 0; y < _height; y++) {
+ for (unsigned int x = 0; x < _width; x++) {
+ texel8 = (uint8 *)texel32;
+ pixel11_offset = pixel00_offset + _width + 1;
+ buf.getARGBAt(
+ pixel00_offset,
+ *(texel8 + P00_OFFSET + A_OFFSET),
+ *(texel8 + P00_OFFSET + R_OFFSET),
+ *(texel8 + P00_OFFSET + G_OFFSET),
+ *(texel8 + P00_OFFSET + B_OFFSET)
+ );
+ if ((x + 1) == _width) {
+ pixel11_offset -= 1;
+ pixel01_offset = pixel00_offset;
+ } else
+ pixel01_offset = pixel00_offset + 1;
+ buf.getARGBAt(
+ pixel01_offset,
+ *(texel8 + P01_OFFSET + A_OFFSET),
+ *(texel8 + P01_OFFSET + R_OFFSET),
+ *(texel8 + P01_OFFSET + G_OFFSET),
+ *(texel8 + P01_OFFSET + B_OFFSET)
+ );
+ if ((y + 1) == _height) {
+ pixel11_offset -= _width;
+ pixel10_offset = pixel00_offset;
+ } else
+ pixel10_offset = pixel00_offset + _width;
+ buf.getARGBAt(
+ pixel10_offset,
+ *(texel8 + P10_OFFSET + A_OFFSET),
+ *(texel8 + P10_OFFSET + R_OFFSET),
+ *(texel8 + P10_OFFSET + G_OFFSET),
+ *(texel8 + P10_OFFSET + B_OFFSET)
+ );
+ buf.getARGBAt(
+ pixel11_offset,
+ *(texel8 + P11_OFFSET + A_OFFSET),
+ *(texel8 + P11_OFFSET + R_OFFSET),
+ *(texel8 + P11_OFFSET + G_OFFSET),
+ *(texel8 + P11_OFFSET + B_OFFSET)
+ );
+ texel32 += 1 << PIXEL_PER_TEXEL_SHIFT;
+ pixel00_offset++;
+ }
+ }
+}
+
+BilinearTexelBuffer::~BilinearTexelBuffer() {
+ delete[] _texels;
+}
+
+static inline int interpolate(int v00, int v01, int v10, int xf, int yf) {
+ return v00 + (((v01 - v00) * xf + (v10 - v00) * yf) >> ZB_POINT_ST_FRAC_BITS);
+}
+
+void BilinearTexelBuffer::getARGBAt(
+ unsigned int pixel,
+ unsigned int ds, unsigned int dt,
+ uint8 &a, uint8 &r, uint8 &g, uint8 &b
+) const {
+ unsigned int p00_offset, p01_offset, p10_offset;
+ uint8 *texel = (uint8 *)(_texels + (pixel << PIXEL_PER_TEXEL_SHIFT));
+ if ((ds + dt) > ZB_POINT_ST_UNIT) {
+ p00_offset = P11_OFFSET;
+ p10_offset = P01_OFFSET;
+ p01_offset = P10_OFFSET;
+ ds = ZB_POINT_ST_UNIT - ds;
+ dt = ZB_POINT_ST_UNIT - dt;
+ } else {
+ p00_offset = P00_OFFSET;
+ p10_offset = P10_OFFSET;
+ p01_offset = P01_OFFSET;
+ }
+ a = interpolate(
+ *(texel + p00_offset + A_OFFSET),
+ *(texel + p01_offset + A_OFFSET),
+ *(texel + p10_offset + A_OFFSET),
+ ds,
+ dt
+ );
+ r = interpolate(
+ *(texel + p00_offset + R_OFFSET),
+ *(texel + p01_offset + R_OFFSET),
+ *(texel + p10_offset + R_OFFSET),
+ ds,
+ dt
+ );
+ g = interpolate(
+ *(texel + p00_offset + G_OFFSET),
+ *(texel + p01_offset + G_OFFSET),
+ *(texel + p10_offset + G_OFFSET),
+ ds,
+ dt
+ );
+ b = interpolate(
+ *(texel + p00_offset + B_OFFSET),
+ *(texel + p01_offset + B_OFFSET),
+ *(texel + p10_offset + B_OFFSET),
+ ds,
+ dt
+ );
+}
+
+}
diff --git a/graphics/tinygl/texelbuffer.h b/graphics/tinygl/texelbuffer.h
new file mode 100644
index 0000000000..651964eee3
--- /dev/null
+++ b/graphics/tinygl/texelbuffer.h
@@ -0,0 +1,85 @@
+/* ResidualVM - A 3D game interpreter
+ *
+ * ResidualVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef GRAPHICS_TEXELBUFFER_H
+#define GRAPHICS_TEXELBUFFER_H
+
+#include "graphics/pixelbuffer.h"
+
+namespace Graphics {
+
+class TexelBuffer {
+public:
+ TexelBuffer(unsigned int width, unsigned int height, unsigned int textureSize);
+ virtual ~TexelBuffer() {};
+
+ void getARGBAt(
+ unsigned int wrap_s, unsigned int wrap_t,
+ int s, int t,
+ uint8 &a, uint8 &r, uint8 &g, uint8 &b
+ ) const;
+
+protected:
+ virtual void getARGBAt(
+ unsigned int pixel,
+ unsigned int ds, unsigned int dt,
+ uint8 &a, uint8 &r, uint8 &g, uint8 &b
+ ) const = 0;
+ unsigned int _width, _height, _fracTextureUnit, _fracTextureMask;
+ float _widthRatio, _heightRatio;
+};
+
+class NearestTexelBuffer : public TexelBuffer {
+public:
+ NearestTexelBuffer(const PixelBuffer &buf, unsigned int width, unsigned int height, unsigned int textureSize);
+ ~NearestTexelBuffer();
+
+protected:
+ void getARGBAt(
+ unsigned int pixel,
+ unsigned int, unsigned int,
+ uint8 &a, uint8 &r, uint8 &g, uint8 &b
+ ) const override;
+
+private:
+ PixelBuffer _buf;
+};
+
+class BilinearTexelBuffer : public TexelBuffer {
+public:
+ BilinearTexelBuffer(const PixelBuffer &buf, unsigned int width, unsigned int height, unsigned int textureSize);
+ ~BilinearTexelBuffer();
+
+protected:
+ void getARGBAt(
+ unsigned int pixel,
+ unsigned int ds, unsigned int dt,
+ uint8 &a, uint8 &r, uint8 &g, uint8 &b
+ ) const override;
+
+private:
+ uint32 *_texels;
+};
+
+}
+
+#endif
diff --git a/graphics/tinygl/texture.cpp b/graphics/tinygl/texture.cpp
index dd3dee16c3..d5b04d1a0d 100644
--- a/graphics/tinygl/texture.cpp
+++ b/graphics/tinygl/texture.cpp
@@ -106,8 +106,10 @@ void free_texture(GLContext *c, GLTexture *t) {
for (int i = 0; i < MAX_TEXTURE_LEVELS; i++) {
im = &t->images[i];
- if (im->pixmap)
- im->pixmap.free();
+ if (im->pixmap) {
+ delete im->pixmap;
+ im->pixmap = nullptr;
+ }
}
gl_free(t);
@@ -137,6 +139,8 @@ void glInitTextures(GLContext *c) {
// textures
c->texture_2d_enabled = 0;
c->current_texture = find_texture(c, 0);
+ c->texture_mag_filter = TGL_LINEAR;
+ c->texture_min_filter = TGL_NEAREST_MIPMAP_LINEAR;
}
void glopBindTexture(GLContext *c, GLParam *p) {
@@ -182,56 +186,40 @@ void glopTexImage2D(GLContext *c, GLParam *p) {
if (border != 0)
error("tglTexImage2D: invalid border");
- Graphics::PixelFormat pf;
- switch (format) {
- case TGL_RGBA:
- case TGL_RGB:
-#if defined(SCUMM_BIG_ENDIAN)
- pf = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 16, 8, 0);
-#elif defined(SCUMM_LITTLE_ENDIAN)
- pf = Graphics::PixelFormat(4, 8, 8, 8, 8, 0, 8, 16, 24);
-#endif
- break;
- case TGL_BGRA:
- case TGL_BGR:
-#if defined(SCUMM_BIG_ENDIAN)
- pf = Graphics::PixelFormat(4, 8, 8, 8, 8, 24, 0, 8, 16);
-#elif defined(SCUMM_LITTLE_ENDIAN)
- pf = Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24);
-#endif
- break;
- default:
- break;
+ c->current_texture->versionNumber++;
+ im = &c->current_texture->images[level];
+ im->xsize = c->_textureSize;
+ im->ysize = c->_textureSize;
+ if (im->pixmap) {
+ delete im->pixmap;
+ im->pixmap = nullptr;
}
- Graphics::PixelBuffer internal(
- pf,
- c->_textureSize * c->_textureSize,
- DisposeAfterUse::NO
- );
if (pixels != NULL) {
+ unsigned int filter;
Graphics::PixelBuffer src(formatType2PixelFormat(format, type), pixels);
- if (width != c->_textureSize || height != c->_textureSize) {
- // we use interpolation for better looking result
- gl_resizeImage(
- internal, c->_textureSize, c->_textureSize,
- src, width, height
+ if (width > c->_textureSize || height > c->_textureSize)
+ filter = c->texture_mag_filter;
+ else
+ filter = c->texture_min_filter;
+ switch (filter) {
+ case TGL_LINEAR_MIPMAP_NEAREST:
+ case TGL_LINEAR_MIPMAP_LINEAR:
+ case TGL_LINEAR:
+ im->pixmap = new Graphics::BilinearTexelBuffer(
+ src,
+ width, height,
+ c->_textureSize
);
- } else {
- internal.copyBuffer(
- 0,
- c->_textureSize * c->_textureSize,
- src
+ break;
+ default:
+ im->pixmap = new Graphics::NearestTexelBuffer(
+ src,
+ width, height,
+ c->_textureSize
);
+ break;
}
}
-
- c->current_texture->versionNumber++;
- im = &c->current_texture->images[level];
- im->xsize = c->_textureSize;
- im->ysize = c->_textureSize;
- if (im->pixmap)
- im->pixmap.free();
- im->pixmap = internal;
}
// TODO: not all tests are done
@@ -253,7 +241,7 @@ error:
}
// TODO: not all tests are done
-void glopTexParameter(GLContext *, GLParam *p) {
+void glopTexParameter(GLContext *c, GLParam *p) {
int target = p[1].i;
int pname = p[2].i;
int param = p[3].i;
@@ -265,9 +253,34 @@ error:
switch (pname) {
case TGL_TEXTURE_WRAP_S:
+ c->texture_wrap_s = param;
+ break;
case TGL_TEXTURE_WRAP_T:
- if (param != TGL_REPEAT)
+ c->texture_wrap_t = param;
+ break;
+ case TGL_TEXTURE_MAG_FILTER:
+ switch (param) {
+ case TGL_NEAREST:
+ case TGL_LINEAR:
+ c->texture_mag_filter = param;
+ break;
+ default:
goto error;
+ }
+ break;
+ case TGL_TEXTURE_MIN_FILTER:
+ switch (param) {
+ case TGL_LINEAR_MIPMAP_NEAREST:
+ case TGL_LINEAR_MIPMAP_LINEAR:
+ case TGL_NEAREST_MIPMAP_NEAREST:
+ case TGL_NEAREST_MIPMAP_LINEAR:
+ case TGL_NEAREST:
+ case TGL_LINEAR:
+ c->texture_min_filter = param;
+ break;
+ default:
+ goto error;
+ }
break;
default:
;
diff --git a/graphics/tinygl/zbuffer.cpp b/graphics/tinygl/zbuffer.cpp
index 1f689af414..b925eaafc1 100644
--- a/graphics/tinygl/zbuffer.cpp
+++ b/graphics/tinygl/zbuffer.cpp
@@ -325,8 +325,10 @@ void FrameBuffer::clearOffscreenBuffer(Buffer *buf) {
buf->used = false;
}
-void FrameBuffer::setTexture(const Graphics::PixelBuffer &texture) {
+void FrameBuffer::setTexture(const Graphics::TexelBuffer *texture, unsigned int wraps, unsigned int wrapt) {
current_texture = texture;
+ wrapS = wraps;
+ wrapT = wrapt;
}
} // end of namespace TinyGL
diff --git a/graphics/tinygl/zbuffer.h b/graphics/tinygl/zbuffer.h
index 8965cc0975..5fdfbe5ec4 100644
--- a/graphics/tinygl/zbuffer.h
+++ b/graphics/tinygl/zbuffer.h
@@ -30,6 +30,7 @@
#define GRAPHICS_TINYGL_ZBUFFER_H_
#include "graphics/pixelbuffer.h"
+#include "graphics/tinygl/texelbuffer.h"
#include "graphics/tinygl/gl.h"
#include "common/rect.h"
@@ -424,7 +425,7 @@ struct FrameBuffer {
void blitOffscreenBuffer(Buffer *buffer);
void selectOffscreenBuffer(Buffer *buffer);
void clearOffscreenBuffer(Buffer *buffer);
- void setTexture(const Graphics::PixelBuffer &texture);
+ void setTexture(const Graphics::TexelBuffer *texture, unsigned int wraps, unsigned int wrapt);
template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawLogic, bool kDepthWrite, bool enableAlphaTest, bool kEnableScissor, bool enableBlending>
void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
@@ -482,9 +483,10 @@ struct FrameBuffer {
unsigned char *dctable;
int *ctable;
- Graphics::PixelBuffer current_texture;
+ const Graphics::TexelBuffer *current_texture;
int _textureSize;
int _textureSizeMask;
+ unsigned int wrapS, wrapT;
FORCEINLINE bool isBlendingEnabled() const { return _blendingEnabled; }
FORCEINLINE void getBlendingFactors(int &sourceFactor, int &destinationFactor) const { sourceFactor = _sourceBlendingFactor; destinationFactor = _destinationBlendingFactor; }
diff --git a/graphics/tinygl/zdirtyrect.cpp b/graphics/tinygl/zdirtyrect.cpp
index 4a3275e310..18fc9e253a 100644
--- a/graphics/tinygl/zdirtyrect.cpp
+++ b/graphics/tinygl/zdirtyrect.cpp
@@ -453,6 +453,8 @@ RasterizationDrawCall::RasterizationState RasterizationDrawCall::captureState()
state.shadowMode = c->shadow_mode;
state.texture2DEnabled = c->texture_2d_enabled;
state.texture = c->current_texture;
+ state.wrapS = c->texture_wrap_s;
+ state.wrapT = c->texture_wrap_t;
state.shadowMaskBuf = c->fb->shadow_mask_buf;
state.depthFunction = c->fb->getDepthFunc();
state.depthWrite = c->fb->getDepthWrite();
@@ -489,6 +491,8 @@ void RasterizationDrawCall::applyState(const RasterizationDrawCall::Rasterizatio
c->shadow_mode = state.shadowMode;
c->texture_2d_enabled = state.texture2DEnabled;
c->current_texture = state.texture;
+ c->texture_wrap_s = state.wrapS;
+ c->texture_wrap_t = state.wrapT;
c->fb->shadow_mask_buf = state.shadowMaskBuf;
memcpy(c->viewport.scale._v, state.viewportScaling, sizeof(c->viewport.scale._v));
diff --git a/graphics/tinygl/zdirtyrect.h b/graphics/tinygl/zdirtyrect.h
index f1a3396ab8..f579294ad3 100644
--- a/graphics/tinygl/zdirtyrect.h
+++ b/graphics/tinygl/zdirtyrect.h
@@ -132,6 +132,7 @@ private:
bool alphaTest;
int alphaFunc, alphaRefValue;
TinyGL::GLTexture *texture;
+ unsigned int wrapS, wrapT;
unsigned char *shadowMaskBuf;
bool operator==(const RasterizationState &other) const;
diff --git a/graphics/tinygl/zgl.h b/graphics/tinygl/zgl.h
index 0711a43386..5cd8904c9f 100644
--- a/graphics/tinygl/zgl.h
+++ b/graphics/tinygl/zgl.h
@@ -40,6 +40,7 @@
#include "graphics/tinygl/zmath.h"
#include "graphics/tinygl/zblit.h"
#include "graphics/tinygl/zdirtyrect.h"
+#include "graphics/tinygl/texelbuffer.h"
namespace TinyGL {
@@ -174,7 +175,7 @@ struct GLVertex {
};
struct GLImage {
- Graphics::PixelBuffer pixmap;
+ Graphics::TexelBuffer *pixmap;
int xsize, ysize;
};
@@ -279,6 +280,10 @@ struct GLContext {
// textures
GLTexture *current_texture;
int texture_2d_enabled;
+ int texture_mag_filter;
+ int texture_min_filter;
+ unsigned int texture_wrap_s;
+ unsigned int texture_wrap_t;
// shared state
GLSharedState shared_state;
diff --git a/graphics/tinygl/ztriangle.cpp b/graphics/tinygl/ztriangle.cpp
index d16e92ad4d..620f3d2510 100644
--- a/graphics/tinygl/ztriangle.cpp
+++ b/graphics/tinygl/ztriangle.cpp
@@ -27,6 +27,7 @@
*/
#include "common/endian.h"
+#include "graphics/tinygl/texelbuffer.h"
#include "graphics/tinygl/zbuffer.h"
#include "graphics/tinygl/zgl.h"
@@ -77,20 +78,12 @@ FORCEINLINE static void putPixelShadow(FrameBuffer *buffer, int buf, unsigned in
template <bool kDepthWrite, bool kLightsMode, bool kSmoothMode, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending>
FORCEINLINE static void putPixelTextureMappingPerspective(FrameBuffer *buffer, int buf,
- Graphics::PixelFormat &textureFormat, Graphics::PixelBuffer &texture, unsigned int *pz, int _a,
- int x, int y, unsigned int &z, unsigned int &t, unsigned int &s, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
+ const Graphics::TexelBuffer *texture, unsigned int wrap_s, unsigned int wrap_t, unsigned int *pz, int _a,
+ int x, int y, unsigned int &z, int &t, int &s, unsigned int &r, unsigned int &g, unsigned int &b, unsigned int &a,
int &dzdx, int &dsdx, int &dtdx, int &drdx, int &dgdx, int &dbdx, unsigned int dadx) {
if ((!kEnableScissor || !buffer->scissorPixel(x + _a, y)) && buffer->compareDepth(z, pz[_a])) {
- unsigned sss = (s & buffer->_textureSizeMask) >> ZB_POINT_ST_FRAC_BITS;
- unsigned ttt = (t & buffer->_textureSizeMask) >> ZB_POINT_ST_FRAC_BITS;
- int pixel = ttt * buffer->_textureSize + sss;
uint8 c_a, c_r, c_g, c_b;
- uint32 *textureBuffer = (uint32 *)texture.getRawBuffer(pixel);
- uint32 col = *textureBuffer;
- c_a = (col >> textureFormat.aShift) & 0xFF;
- c_r = (col >> textureFormat.rShift) & 0xFF;
- c_g = (col >> textureFormat.gShift) & 0xFF;
- c_b = (col >> textureFormat.bShift) & 0xFF;
+ texture->getARGBAt(wrap_s, wrap_t, s, t, c_a, c_r, c_g, c_b);
if (kLightsMode) {
unsigned int l_a = (a >> (ZB_POINT_ALPHA_BITS - 8));
unsigned int l_r = (r >> (ZB_POINT_RED_BITS - 8));
@@ -116,8 +109,7 @@ FORCEINLINE static void putPixelTextureMappingPerspective(FrameBuffer *buffer, i
template <bool kInterpRGB, bool kInterpZ, bool kInterpST, bool kInterpSTZ, int kDrawLogic, bool kDepthWrite, bool kAlphaTestEnabled, bool kEnableScissor, bool kBlendingEnabled>
void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2) {
- Graphics::PixelBuffer texture;
- Graphics::PixelFormat textureFormat;
+ const Graphics::TexelBuffer *texture;
float fdzdx = 0, fndzdx = 0, ndszdx = 0, ndtzdx = 0;
ZBufferPoint *tp, *pr1 = 0, *pr2 = 0, *l1 = 0, *l2 = 0;
@@ -270,8 +262,6 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
if ((kInterpST || kInterpSTZ) && (kDrawLogic == DRAW_FLAT || kDrawLogic == DRAW_SMOOTH)) {
texture = current_texture;
- textureFormat = texture.getFormat();
- assert(textureFormat.bytesPerPixel == 4);
fdzdx = (float)dzdx;
fndzdx = NB_INTERP * fdzdx;
ndszdx = NB_INTERP * dszdx;
@@ -514,7 +504,8 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
}
} else if (kInterpST || kInterpSTZ) {
unsigned int *pz;
- unsigned int s, t, z, r, g, b, a;
+ int s, t;
+ unsigned int z, r, g, b, a;
int n;
float sz, tz, fz, zinv;
int dsdx, dtdx;
@@ -546,7 +537,7 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
zinv = (float)(1.0 / fz);
}
for (int _a = 0; _a < NB_INTERP; _a++) {
- putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, textureFormat, texture,
+ putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, texture, wrapS, wrapT,
pz, _a, x, y, z, t, s, r, g, b, a, dzdx, dsdx, dtdx, drdx, dgdx, dbdx, dadx);
}
pz += NB_INTERP;
@@ -568,7 +559,7 @@ void FrameBuffer::fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint
}
while (n >= 0) {
- putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, textureFormat, texture,
+ putPixelTextureMappingPerspective<kDepthWrite, kInterpRGB, kDrawLogic == DRAW_SMOOTH, kAlphaTestEnabled, kEnableScissor, kBlendingEnabled>(this, buf, texture, wrapS, wrapT,
pz, 0, x, y, z, t, s, r, g, b, a, dzdx, dsdx, dtdx, drdx, dgdx, dbdx, dadx);
pz += 1;
buf += 1;
Commit: 6f8303c2e32b0a3106229fa3c887833b34c02d5c
https://github.com/scummvm/scummvm/commit/6f8303c2e32b0a3106229fa3c887833b34c02d5c
Author: Vincent Pelletier (plr.vincent at gmail.com)
Date: 2020-11-12T08:16:40+01:00
Commit Message:
MYST3: Use TGL_UNSIGNED_SHORT_5_6_5 texture format in gfx_tinygl
It is now supported by TinyGL.
Changed paths:
engines/myst3/gfx_tinygl_texture.cpp
diff --git a/engines/myst3/gfx_tinygl_texture.cpp b/engines/myst3/gfx_tinygl_texture.cpp
index 6b8aa139c1..4a78730e9b 100644
--- a/engines/myst3/gfx_tinygl_texture.cpp
+++ b/engines/myst3/gfx_tinygl_texture.cpp
@@ -35,7 +35,7 @@ TinyGLTexture::TinyGLTexture(const Graphics::Surface *surface) {
sourceFormat = TGL_UNSIGNED_BYTE;
} else if (format.bytesPerPixel == 2) {
internalFormat = TGL_RGB;
- sourceFormat = TGL_UNSIGNED_BYTE; // UNSIGNED_SHORT_5_6_5 not provided
+ sourceFormat = TGL_UNSIGNED_SHORT_5_6_5;
} else
error("Unknown pixel format");
Commit: 02294ee7175ac3e2b400569508a432c19ee2be13
https://github.com/scummvm/scummvm/commit/02294ee7175ac3e2b400569508a432c19ee2be13
Author: Vincent Pelletier (plr.vincent at gmail.com)
Date: 2020-11-12T08:16:52+01:00
Commit Message:
GRAPHICS: Use memcpy when copying to same-format-no-alpha destination
Accelerates when source format is compatible with destination except for
alpha channel bit-loss. Ex:
from: 32bits A << 24 | R << 16 | G << 8 | B
to: 32bits R << 16 | G << 8 | B
Changed paths:
graphics/pixelbuffer.cpp
diff --git a/graphics/pixelbuffer.cpp b/graphics/pixelbuffer.cpp
index e762b94215..306cf14cbe 100644
--- a/graphics/pixelbuffer.cpp
+++ b/graphics/pixelbuffer.cpp
@@ -87,7 +87,17 @@ void PixelBuffer::clear(int length) {
}
void PixelBuffer::copyBuffer(int thisFrom, int otherFrom, int length, const PixelBuffer &buf) {
- if (buf._format == _format) {
+ if (buf._format.bytesPerPixel == _format.bytesPerPixel &&
+ buf._format.rShift == _format.rShift &&
+ buf._format.gShift == _format.gShift &&
+ buf._format.bShift == _format.bShift &&
+ buf._format.rLoss == _format.rLoss &&
+ buf._format.gLoss == _format.gLoss &&
+ buf._format.bLoss == _format.bLoss && (
+ _format.aLoss = 8 ||
+ buf._format.aLoss == _format.aLoss
+ )
+ ) {
memcpy(_buffer + thisFrom * _format.bytesPerPixel, buf._buffer + otherFrom * _format.bytesPerPixel, length * _format.bytesPerPixel);
} else {
uint8 r, g, b, a;
More information about the Scummvm-git-logs
mailing list