2014-08-13 18:52:52 +02:00
|
|
|
/* 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 AUTHORS
|
|
|
|
* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
/*
|
|
|
|
* This file is based on, or a modified version of code from TinyGL (C) 1997-1998 Fabrice Bellard,
|
|
|
|
* which is licensed under the zlib-license (see LICENSE).
|
|
|
|
* It also has modifications by the ResidualVM-team, which are covered under the GPLv2 (or later).
|
|
|
|
*/
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2006-05-16 10:02:27 +00:00
|
|
|
// Z buffer: 16,32 bits Z / 16 bits color
|
|
|
|
|
2011-04-17 01:00:10 +02:00
|
|
|
#include "common/scummsys.h"
|
2012-01-16 17:12:14 +01:00
|
|
|
#include "common/endian.h"
|
|
|
|
|
2009-05-08 07:32:33 +00:00
|
|
|
#include "graphics/tinygl/zbuffer.h"
|
2012-01-16 17:12:14 +01:00
|
|
|
#include "graphics/tinygl/zgl.h"
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2009-05-25 13:19:29 +00:00
|
|
|
namespace TinyGL {
|
|
|
|
|
2006-05-16 10:02:27 +00:00
|
|
|
// adr must be aligned on an 'int'
|
|
|
|
void memset_s(void *adr, int val, int count) {
|
2014-02-20 17:56:55 +01:00
|
|
|
int n, v;
|
2006-05-16 10:02:27 +00:00
|
|
|
unsigned int *p;
|
|
|
|
unsigned short *q;
|
|
|
|
|
|
|
|
p = (unsigned int *)adr;
|
|
|
|
v = val | (val << 16);
|
|
|
|
|
|
|
|
n = count >> 3;
|
2014-02-20 17:56:55 +01:00
|
|
|
for (int i = 0; i < n; i++) {
|
2006-05-16 10:02:27 +00:00
|
|
|
p[0] = v;
|
|
|
|
p[1] = v;
|
|
|
|
p[2] = v;
|
|
|
|
p[3] = v;
|
|
|
|
p += 4;
|
|
|
|
}
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2006-05-16 10:02:27 +00:00
|
|
|
q = (unsigned short *) p;
|
|
|
|
n = count & 7;
|
2014-02-20 17:56:55 +01:00
|
|
|
for (int i = 0; i < n; i++)
|
2006-05-16 10:02:27 +00:00
|
|
|
*q++ = val;
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
|
|
|
|
2006-05-16 10:02:27 +00:00
|
|
|
void memset_l(void *adr, int val, int count) {
|
2014-02-20 17:56:55 +01:00
|
|
|
int n, v;
|
2006-05-16 10:02:27 +00:00
|
|
|
unsigned int *p;
|
|
|
|
|
|
|
|
p = (unsigned int *)adr;
|
|
|
|
v = val;
|
|
|
|
n = count >> 2;
|
2014-02-20 17:56:55 +01:00
|
|
|
for (int i = 0; i < n; i++) {
|
2006-05-16 10:02:27 +00:00
|
|
|
p[0] = v;
|
|
|
|
p[1] = v;
|
|
|
|
p[2] = v;
|
|
|
|
p[3] = v;
|
|
|
|
p += 4;
|
|
|
|
}
|
2006-05-16 07:28:47 +00:00
|
|
|
|
2014-02-20 18:46:49 +01:00
|
|
|
n = count & 3;
|
|
|
|
for (int i = 0; i < n; i++)
|
|
|
|
*p++ = val;
|
2006-05-16 07:28:47 +00:00
|
|
|
}
|
|
|
|
|
2014-07-03 16:26:01 +02:00
|
|
|
FrameBuffer::FrameBuffer(int width, int height, const Graphics::PixelBuffer &frame_buffer) : _depthWrite(true) {
|
2014-06-06 01:34:10 +02:00
|
|
|
int size;
|
2005-01-12 15:20:02 +00:00
|
|
|
|
2014-06-17 17:00:20 +02:00
|
|
|
this->xsize = width;
|
|
|
|
this->ysize = height;
|
2014-06-06 01:34:10 +02:00
|
|
|
this->cmode = frame_buffer.getFormat();
|
2016-07-16 07:56:03 +00:00
|
|
|
this->pixelbytes = this->cmode.bytesPerPixel;
|
2014-06-06 01:34:10 +02:00
|
|
|
this->pixelbits = this->cmode.bytesPerPixel * 8;
|
|
|
|
this->linesize = (xsize * this->pixelbytes + 3) & ~3;
|
|
|
|
|
2014-08-01 19:21:35 +02:00
|
|
|
this->setScissorRectangle(0, xsize, 0, ysize);
|
|
|
|
|
2014-06-06 01:34:10 +02:00
|
|
|
size = this->xsize * this->ysize * sizeof(unsigned int);
|
|
|
|
|
2014-08-09 12:00:43 +02:00
|
|
|
this->_zbuf = (unsigned int *)gl_malloc(size);
|
2014-06-06 01:34:10 +02:00
|
|
|
|
|
|
|
if (!frame_buffer) {
|
2014-06-17 17:00:20 +02:00
|
|
|
byte *pixelBuffer = (byte *)gl_malloc(this->ysize * this->linesize);
|
|
|
|
this->pbuf.set(this->cmode, pixelBuffer);
|
2014-06-06 01:34:10 +02:00
|
|
|
this->frame_buffer_allocated = 1;
|
|
|
|
} else {
|
|
|
|
this->frame_buffer_allocated = 0;
|
|
|
|
this->pbuf = frame_buffer;
|
2006-05-16 10:02:27 +00:00
|
|
|
}
|
2014-06-06 01:34:10 +02:00
|
|
|
|
|
|
|
this->current_texture = NULL;
|
|
|
|
this->shadow_mask_buf = NULL;
|
|
|
|
|
|
|
|
this->buffer.pbuf = this->pbuf.getRawBuffer();
|
2014-08-09 12:00:43 +02:00
|
|
|
this->buffer.zbuf = this->_zbuf;
|
2014-06-18 00:14:55 +02:00
|
|
|
_blendingEnabled = false;
|
2014-07-04 08:43:19 +02:00
|
|
|
_alphaTestEnabled = false;
|
2014-08-10 16:13:50 +03:00
|
|
|
_depthTestEnabled = false;
|
2014-07-05 08:00:22 +02:00
|
|
|
_depthFunc = TGL_LESS;
|
2014-06-06 01:34:10 +02:00
|
|
|
}
|
|
|
|
|
2014-06-13 14:58:07 +02:00
|
|
|
FrameBuffer::~FrameBuffer() {
|
2014-06-06 01:34:10 +02:00
|
|
|
if (frame_buffer_allocated)
|
|
|
|
pbuf.free();
|
2014-08-09 12:00:43 +02:00
|
|
|
gl_free(_zbuf);
|
2005-01-12 15:20:02 +00:00
|
|
|
}
|
2009-05-25 13:19:29 +00:00
|
|
|
|
2014-06-17 17:00:43 +02:00
|
|
|
Buffer *FrameBuffer::genOffscreenBuffer() {
|
2013-01-11 12:39:12 +01:00
|
|
|
Buffer *buf = (Buffer *)gl_malloc(sizeof(Buffer));
|
2014-06-06 01:34:10 +02:00
|
|
|
buf->pbuf = (byte *)gl_malloc(this->ysize * this->linesize);
|
|
|
|
int size = this->xsize * this->ysize * sizeof(unsigned int);
|
2013-01-11 12:39:12 +01:00
|
|
|
buf->zbuf = (unsigned int *)gl_malloc(size);
|
2012-02-13 21:28:19 +01:00
|
|
|
|
2013-01-11 12:39:12 +01:00
|
|
|
return buf;
|
|
|
|
}
|
2012-02-13 17:59:48 +01:00
|
|
|
|
2014-06-13 14:58:07 +02:00
|
|
|
void FrameBuffer::delOffscreenBuffer(Buffer *buf) {
|
2013-01-11 12:39:12 +01:00
|
|
|
gl_free(buf->pbuf);
|
|
|
|
gl_free(buf->zbuf);
|
|
|
|
gl_free(buf);
|
2012-02-13 17:59:48 +01:00
|
|
|
}
|
|
|
|
|
2014-08-09 12:00:43 +02:00
|
|
|
void FrameBuffer::clear(int clearZ, int z, int clearColor, int r, int g, int b) {
|
|
|
|
if (clearZ) {
|
|
|
|
memset_l(this->_zbuf, z, this->xsize * this->ysize);
|
2014-06-06 01:34:10 +02:00
|
|
|
}
|
2014-08-09 12:00:43 +02:00
|
|
|
if (clearColor) {
|
2014-08-10 19:36:32 +02:00
|
|
|
byte *pp = this->pbuf.getRawBuffer();
|
|
|
|
uint32 color = this->cmode.RGBToColor(r, g, b);
|
2014-06-06 01:34:10 +02:00
|
|
|
for (int y = 0; y < this->ysize; y++) {
|
|
|
|
memset_s(pp, color, this->xsize);
|
|
|
|
pp = pp + this->linesize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-08-09 12:00:43 +02:00
|
|
|
void FrameBuffer::clearRegion(int x, int y, int w, int h, int clearZ, int z, int clearColor, int r, int g, int b) {
|
|
|
|
if (clearZ) {
|
2014-08-01 19:26:13 +02:00
|
|
|
for (int row = y; row < y + h; row++) {
|
2014-08-09 12:00:43 +02:00
|
|
|
memset_l(this->_zbuf + x + (row * this->xsize), z, w);
|
2014-08-01 19:26:13 +02:00
|
|
|
}
|
|
|
|
}
|
2014-08-09 12:00:43 +02:00
|
|
|
if (clearColor) {
|
2014-08-10 19:36:32 +02:00
|
|
|
byte *pp = this->pbuf.getRawBuffer() + y * this->linesize;
|
|
|
|
uint32 color = this->cmode.RGBToColor(r, g, b);
|
2014-08-01 19:26:13 +02:00
|
|
|
for (int row = y; row < y + h; row++) {
|
|
|
|
memset_s(pp + x * this->pixelbytes, color, w);
|
|
|
|
pp = pp + this->linesize;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
|
2014-06-17 17:00:43 +02:00
|
|
|
void FrameBuffer::blitOffscreenBuffer(Buffer *buf) {
|
2012-02-13 17:59:48 +01:00
|
|
|
// TODO: could be faster, probably.
|
2013-01-11 12:39:12 +01:00
|
|
|
if (buf->used) {
|
2014-06-06 01:34:10 +02:00
|
|
|
for (int i = 0; i < this->xsize * this->ysize; ++i) {
|
2013-01-11 12:39:12 +01:00
|
|
|
unsigned int d1 = buf->zbuf[i];
|
2014-08-09 12:00:43 +02:00
|
|
|
unsigned int d2 = this->_zbuf[i];
|
2012-02-13 17:59:48 +01:00
|
|
|
if (d1 > d2) {
|
2016-07-16 07:56:03 +00:00
|
|
|
const int offset = i * this->pixelbytes;
|
|
|
|
memcpy(this->pbuf.getRawBuffer() + offset, buf->pbuf + offset, this->pixelbytes);
|
2014-08-09 12:00:43 +02:00
|
|
|
memcpy(this->_zbuf + i, buf->zbuf + i, sizeof(int));
|
2012-02-13 17:59:48 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-17 17:00:43 +02:00
|
|
|
void FrameBuffer::selectOffscreenBuffer(Buffer *buf) {
|
2013-01-11 12:39:12 +01:00
|
|
|
if (buf) {
|
2014-06-06 01:34:10 +02:00
|
|
|
this->pbuf = buf->pbuf;
|
2014-08-09 12:00:43 +02:00
|
|
|
this->_zbuf = buf->zbuf;
|
2013-01-11 12:39:12 +01:00
|
|
|
buf->used = true;
|
|
|
|
} else {
|
2014-06-06 01:34:10 +02:00
|
|
|
this->pbuf = this->buffer.pbuf;
|
2014-08-09 12:00:43 +02:00
|
|
|
this->_zbuf = this->buffer.zbuf;
|
2012-02-13 21:28:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-06-17 17:00:43 +02:00
|
|
|
void FrameBuffer::clearOffscreenBuffer(Buffer *buf) {
|
2014-06-06 01:34:10 +02:00
|
|
|
memset(buf->pbuf, 0, this->ysize * this->linesize);
|
|
|
|
memset(buf->zbuf, 0, this->ysize * this->xsize * sizeof(unsigned int));
|
2013-01-11 12:39:12 +01:00
|
|
|
buf->used = false;
|
|
|
|
}
|
|
|
|
|
2014-06-17 17:00:43 +02:00
|
|
|
void FrameBuffer::setTexture(const Graphics::PixelBuffer &texture) {
|
2014-06-11 16:11:47 +02:00
|
|
|
current_texture = texture;
|
|
|
|
}
|
|
|
|
|
2009-05-25 13:19:29 +00:00
|
|
|
} // end of namespace TinyGL
|