ScummVM API documentation
zbuffer.h
1 /* ScummVM - Graphic Adventure Engine
2  *
3  * ScummVM is the legal property of its developers, whose names
4  * are too numerous to list here. Please refer to the COPYRIGHT
5  * file distributed with this source distribution.
6  *
7  * This program is free software: you can redistribute it and/or modify
8  * it under the terms of the GNU General Public License as published by
9  * the Free Software Foundation, either version 3 of the License, or
10  * (at your option) any later version.
11  *
12  * This program is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15  * GNU General Public License for more details.
16  *
17  * You should have received a copy of the GNU General Public License
18  * along with this program. If not, see <http://www.gnu.org/licenses/>.
19  *
20  */
21 
22 /*
23  * This file is based on, or a modified version of code from TinyGL (C) 1997-2022 Fabrice Bellard,
24  * which is licensed under the MIT license (see LICENSE).
25  * It also has modifications by the ResidualVM-team, which are covered under the GPLv2 (or later).
26  */
27 
28 #ifndef GRAPHICS_TINYGL_ZBUFFER_H_
29 #define GRAPHICS_TINYGL_ZBUFFER_H_
30 
31 #include "graphics/surface.h"
32 #include "graphics/tinygl/texelbuffer.h"
33 #include "graphics/tinygl/gl.h"
34 
35 #include "common/rect.h"
36 #include "common/textconsole.h"
37 
38 namespace TinyGL {
39 
40 // Z buffer
41 
42 #define ZB_Z_BITS 16
43 
44 #define ZB_FOG_BITS 16
45 #define ZB_FOG_MAX ( (1 << ZB_FOG_BITS) - 1 )
46 
47 #define ZB_POINT_Z_FRAC_BITS 14
48 
49 #define ZB_POINT_ST_FRAC_BITS 14
50 #define ZB_POINT_ST_FRAC_SHIFT (ZB_POINT_ST_FRAC_BITS - 1)
51 #define ZB_POINT_ST_MAX ( (_textureSize << ZB_POINT_ST_FRAC_BITS) - 1 )
52 
53 #define ZB_POINT_RED_BITS 16
54 #define ZB_POINT_RED_FRAC_BITS 8
55 #define ZB_POINT_RED_FRAC_SHIFT (ZB_POINT_RED_FRAC_BITS - 1)
56 #define ZB_POINT_RED_MAX ( (1 << ZB_POINT_RED_BITS) - 1 )
57 
58 #define ZB_POINT_GREEN_BITS 16
59 #define ZB_POINT_GREEN_FRAC_BITS 8
60 #define ZB_POINT_GREEN_FRAC_SHIFT (ZB_POINT_GREEN_FRAC_BITS - 1)
61 #define ZB_POINT_GREEN_MAX ( (1 << ZB_POINT_GREEN_BITS) - 1 )
62 
63 #define ZB_POINT_BLUE_BITS 16
64 #define ZB_POINT_BLUE_FRAC_BITS 8
65 #define ZB_POINT_BLUE_FRAC_SHIFT (ZB_POINT_BLUE_FRAC_BITS - 1)
66 #define ZB_POINT_BLUE_MAX ( (1 << ZB_POINT_BLUE_BITS) - 1 )
67 
68 #define ZB_POINT_ALPHA_BITS 16
69 #define ZB_POINT_ALPHA_FRAC_BITS 8
70 #define ZB_POINT_ALPHA_FRAC_SHIFT (ZB_POINT_ALPHA_FRAC_BITS - 1)
71 #define ZB_POINT_ALPHA_MAX ( (1 << ZB_POINT_ALPHA_BITS) - 1 )
72 
73 #define RGB_TO_PIXEL(r, g, b) _pbufFormat.ARGBToColor(255, r, g, b) // Default to 255 alpha aka solid colour.
74 
75 static const int DRAW_DEPTH_ONLY = 0;
76 static const int DRAW_FLAT = 1;
77 static const int DRAW_SMOOTH = 2;
78 
79 struct GLTextureEnv; // defined in zdirtyrect.h
80 
81 struct Buffer {
82  byte *pbuf;
83  uint *zbuf;
84  bool used;
85 };
86 
87 struct ZBufferPoint {
88  int x, y, z; // integer coordinates in the zbuffer
89  int s, t; // coordinates for the mapping
90  int r, g, b, a; // color indexes
91  float sz, tz; // temporary coordinates for mapping
92  int f; // fog factor
93 
94  bool operator==(const ZBufferPoint &other) const {
95  return
96  x == other.x &&
97  y == other.y &&
98  z == other.z &&
99  s == other.s &&
100  t == other.t &&
101  r == other.r &&
102  g == other.g &&
103  b == other.b &&
104  a == other.a;
105  }
106 };
107 
108 struct FrameBuffer {
109  FrameBuffer(int width, int height, const Graphics::PixelFormat &format, bool enableStencilBuffer);
110  ~FrameBuffer();
111 
112  Graphics::PixelFormat getPixelFormat() {
113  return _pbufFormat;
114  }
115 
116  byte *getPixelBuffer() {
117  return _pbuf;
118  }
119 
120  int getPixelBufferWidth() {
121  return _pbufWidth;
122  }
123 
124  int getPixelBufferHeight() {
125  return _pbufHeight;
126  }
127 
128  int getPixelBufferPitch() {
129  return _pbufPitch;
130  }
131 
132  int getPixelBufferBpp() {
133  return _pbufBpp;
134  }
135 
136  const uint *getZBuffer() {
137  return _zbuf;
138  }
139 
140  Graphics::Surface *copyFromFrameBuffer(const Graphics::PixelFormat &dstFormat) {
141  Graphics::Surface tmp;
142  tmp.init(_pbufWidth, _pbufHeight, _pbufPitch, _pbuf, _pbufFormat);
143  return tmp.convertTo(dstFormat);
144  }
145 
146  void getSurfaceRef(Graphics::Surface &surface) {
147  surface.init(_pbufWidth, _pbufHeight, _pbufPitch, _pbuf, _pbufFormat);
148  }
149 
150 private:
151 
152  FORCEINLINE void setPixelAt(int pixel, uint32 value) {
153  switch (_pbufBpp) {
154  case 2:
155  ((uint16 *) _pbuf)[pixel] = value;
156  return;
157  case 3:
158  pixel *= 3;
159 #if defined(SCUMM_BIG_ENDIAN)
160  _pbuf[pixel + 0] = (value >> 16) & 0xFF;
161  _pbuf[pixel + 1] = (value >> 8) & 0xFF;
162  _pbuf[pixel + 2] = value & 0xFF;
163 #elif defined(SCUMM_LITTLE_ENDIAN)
164  _pbuf[pixel + 0] = value & 0xFF;
165  _pbuf[pixel + 1] = (value >> 8) & 0xFF;
166  _pbuf[pixel + 2] = (value >> 16) & 0xFF;
167 #endif
168  return;
169  case 4:
170  ((uint32 *) _pbuf)[pixel] = value;
171  return;
172  }
173  error("setPixelAt: Unhandled bytesPerPixel %d", int(_pbufBpp));
174  }
175 
176  FORCEINLINE uint32 getPixelAt(int i) const {
177  switch (_pbufBpp) {
178  case 2:
179  return ((uint16 *) _pbuf)[i];
180  case 3:
181  i *= 3;
182 #if defined(SCUMM_BIG_ENDIAN)
183  return (_pbuf[i + 0] << 16) | (_pbuf[i + 1] << 8) | _pbuf[i + 2];
184 #elif defined(SCUMM_LITTLE_ENDIAN)
185  return _pbuf[i + 0] | (_pbuf[i + 1] << 8) | (_pbuf[i + 2] << 16);
186 #endif
187  case 4:
188  return ((uint32 *) _pbuf)[i];
189  }
190  error("getPixelAt: Unhandled bytesPerPixel %d", int(_pbufBpp));
191  }
192 
193  FORCEINLINE bool compareDepth(uint &zSrc, uint &zDst) {
194  if (!_depthTestEnabled)
195  return true;
196 
197  switch (_depthFunc) {
198  case TGL_NEVER:
199  break;
200  case TGL_LESS:
201  if (zDst < zSrc)
202  return true;
203  break;
204  case TGL_EQUAL:
205  if (zDst == zSrc)
206  return true;
207  break;
208  case TGL_LEQUAL:
209  if (zDst <= zSrc)
210  return true;
211  break;
212  case TGL_GREATER:
213  if (zDst > zSrc)
214  return true;
215  break;
216  case TGL_NOTEQUAL:
217  if (zDst != zSrc)
218  return true;
219  break;
220  case TGL_GEQUAL:
221  if (zDst >= zSrc)
222  return true;
223  break;
224  case TGL_ALWAYS:
225  return true;
226  }
227  return false;
228  }
229 
230  FORCEINLINE bool checkAlphaTest(byte aSrc) {
231  if (!_alphaTestEnabled)
232  return true;
233 
234  switch (_alphaTestFunc) {
235  case TGL_NEVER:
236  break;
237  case TGL_LESS:
238  if (aSrc < _alphaTestRefVal)
239  return true;
240  break;
241  case TGL_EQUAL:
242  if (aSrc == _alphaTestRefVal)
243  return true;
244  break;
245  case TGL_LEQUAL:
246  if (aSrc <= _alphaTestRefVal)
247  return true;
248  break;
249  case TGL_GREATER:
250  if (aSrc > _alphaTestRefVal)
251  return true;
252  break;
253  case TGL_NOTEQUAL:
254  if (aSrc != _alphaTestRefVal)
255  return true;
256  break;
257  case TGL_GEQUAL:
258  if (aSrc >= _alphaTestRefVal)
259  return true;
260  break;
261  case TGL_ALWAYS:
262  return true;
263  }
264  return false;
265  }
266 
267  FORCEINLINE bool stencilTest(byte sSrc) {
268  switch (_stencilTestFunc) {
269  case TGL_NEVER:
270  break;
271  case TGL_LESS:
272  if ((_stencilRefVal & _stencilMask) < (sSrc & _stencilMask))
273  return true;
274  break;
275  case TGL_LEQUAL:
276  if ((_stencilRefVal & _stencilMask) <= (sSrc & _stencilMask))
277  return true;
278  break;
279  case TGL_GREATER:
280  if ((_stencilRefVal & _stencilMask) > (sSrc & _stencilMask))
281  return true;
282  break;
283  case TGL_GEQUAL:
284  if ((_stencilRefVal & _stencilMask) >= (sSrc & _stencilMask))
285  return true;
286  break;
287  case TGL_EQUAL:
288  if ((_stencilRefVal & _stencilMask) == (sSrc & _stencilMask))
289  return true;
290  break;
291  case TGL_NOTEQUAL:
292  if ((_stencilRefVal & _stencilMask) != (sSrc & _stencilMask))
293  return true;
294  break;
295  case TGL_ALWAYS:
296  return true;
297  }
298  return false;
299  }
300 
301  FORCEINLINE void stencilOp(bool stencilTestResult, bool depthTestResult, byte *sDst) {
302  int op = !stencilTestResult ? _stencilSfail : !depthTestResult ? _stencilDpfail : _stencilDppass;
303  byte oldValue = *sDst;
304  byte newValue = oldValue;
305  switch (op) {
306  case TGL_KEEP:
307  return;
308  case TGL_ZERO:
309  newValue = 0;
310  break;
311  case TGL_REPLACE:
312  newValue = _stencilRefVal;
313  break;
314  case TGL_INCR:
315  if (newValue < 255)
316  newValue++;
317  break;
318  case TGL_INCR_WRAP:
319  newValue++;
320  break;
321  case TGL_DECR:
322  if (newValue > 0)
323  newValue--;
324  break;
325  case TGL_DECR_WRAP:
326  newValue--;
327  break;
328  case TGL_INVERT:
329  newValue = ~newValue;
330  }
331  *sDst = (newValue & _stencilWriteMask) | (oldValue & ~_stencilWriteMask);
332  }
333 
334  template <bool kEnableAlphaTest, bool kBlendingEnabled>
335  FORCEINLINE void writePixel(int pixel, int value) {
336  writePixel<kEnableAlphaTest, kBlendingEnabled, false>(pixel, value, 0);
337  }
338 
339  template <bool kEnableAlphaTest, bool kBlendingEnabled, bool kDepthWrite>
340  FORCEINLINE void writePixel(int pixel, int value, uint z) {
341  if (kBlendingEnabled == false) {
342  setPixelAt(pixel, value);
343  if (kDepthWrite) {
344  _zbuf[pixel] = z;
345  }
346  } else {
347  byte rSrc, gSrc, bSrc, aSrc;
348  _pbufFormat.colorToARGB(value, aSrc, rSrc, gSrc, bSrc);
349 
350  writePixel<kEnableAlphaTest, kBlendingEnabled, kDepthWrite>(pixel, aSrc, rSrc, gSrc, bSrc, z);
351  }
352  }
353 
354  FORCEINLINE void writePixel(int pixel, int value) {
355  if (_alphaTestEnabled) {
356  writePixel<true>(pixel, value);
357  } else {
358  writePixel<false>(pixel, value);
359  }
360  }
361 
362  template <bool kDepthWrite, bool kSmoothMode, bool kFogMode, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending, bool kStencilEnabled, bool kDepthTestEnabled>
363  void putPixelNoTexture(int fbOffset, uint *pz, byte *ps, int _a,
364  int x, int y, uint &z, uint &r, uint &g, uint &b, uint &a,
365  int &dzdx, int &drdx, int &dgdx, int &dbdx, uint dadx,
366  uint &fog, int fog_r, int fog_g, int fog_b, int &dfdx,
367  bool kStippleEnabled);
368 
369  enum class ColorMode {
370  NoInterpolation,
371  Default, // GL_TEXTURE_ENV_MODE == GL_MODULATE
372  CustomTexEnv
373  };
374 
375  template <bool kDepthWrite, bool kSmoothMode, bool kFogMode, bool kEnableAlphaTest, bool kEnableScissor, bool kEnableBlending, bool kStencilEnabled, bool kDepthTestEnabled>
376  void putPixelTexture(int fbOffset, const TexelBuffer *texture,
377  FrameBuffer::ColorMode colorMode,
378  uint wrap_s, uint wrap_t, uint *pz, byte *ps, int _a,
379  int x, int y, uint &z, int &t, int &s,
380  uint &r, uint &g, uint &b, uint &a,
381  int &dzdx, int &dsdx, int &dtdx, int &drdx, int &dgdx, int &dbdx, uint dadx,
382  uint &fog, int fog_r, int fog_g, int fog_b, int &dfdx);
383 
384  template <bool kDepthWrite, bool kEnableScissor, bool kStencilEnabled, bool kDepthTestEnabled>
385  void putPixelDepth(uint *pz, byte *ps, int _a, int x, int y, uint &z, int &dzdx,
386  bool stippleEnabled);
387 
388 
389  template <bool kEnableAlphaTest>
390  FORCEINLINE void writePixel(int pixel, int value) {
391  if (_blendingEnabled) {
392  writePixel<kEnableAlphaTest, true>(pixel, value);
393  } else {
394  writePixel<kEnableAlphaTest, false>(pixel, value);
395  }
396  }
397 
398  FORCEINLINE void writePixel(int pixel, byte rSrc, byte gSrc, byte bSrc) {
399  writePixel(pixel, 255, rSrc, gSrc, bSrc);
400  }
401 
402  FORCEINLINE bool scissorPixel(int x, int y) {
403  return !_clipRectangle.contains(x, y);
404  }
405 
406 public:
407 
408  FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc) {
409  if (_alphaTestEnabled) {
410  writePixel<true>(pixel, aSrc, rSrc, gSrc, bSrc);
411  } else {
412  writePixel<false>(pixel, aSrc, rSrc, gSrc, bSrc);
413  }
414  }
415 
416 private:
417 
418  template <bool kEnableAlphaTest>
419  FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc) {
420  if (_blendingEnabled) {
421  writePixel<kEnableAlphaTest, true>(pixel, aSrc, rSrc, gSrc, bSrc);
422  } else {
423  writePixel<kEnableAlphaTest, false>(pixel, aSrc, rSrc, gSrc, bSrc);
424  }
425  }
426 
427  template <bool kEnableAlphaTest, bool kBlendingEnabled>
428  FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc) {
429  writePixel<kEnableAlphaTest, kBlendingEnabled, false>(pixel, aSrc, rSrc, gSrc, bSrc, 0);
430  }
431 
432  template <bool kEnableAlphaTest, bool kBlendingEnabled, bool kDepthWrite>
433  FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc, uint z) {
434  writePixel<kEnableAlphaTest, kBlendingEnabled, kDepthWrite, false>(pixel, aSrc, rSrc, gSrc, bSrc, z, 0.0f, 0, 0, 0);
435  }
436 
437  template <bool kEnableAlphaTest, bool kBlendingEnabled, bool kDepthWrite, bool kFogMode>
438  FORCEINLINE void writePixel(int pixel, byte aSrc, byte rSrc, byte gSrc, byte bSrc, float z, uint fog, byte fog_r, byte fog_g, byte fog_b) {
439  if (kEnableAlphaTest) {
440  if (!checkAlphaTest(aSrc))
441  return;
442  }
443 
444  if (kDepthWrite) {
445  _zbuf[pixel] = z;
446  }
447 
448  if (kFogMode) {
449  int oneMinusFog = (1 << ZB_FOG_BITS) - fog;
450  int finalR = (rSrc * fog + fog_r * oneMinusFog) >> ZB_FOG_BITS;
451  int finalG = (gSrc * fog + fog_g * oneMinusFog) >> ZB_FOG_BITS;
452  int finalB = (bSrc * fog + fog_b * oneMinusFog) >> ZB_FOG_BITS;
453  if (finalR > 255) {
454  rSrc = 255;
455  } else {
456  rSrc = finalR;
457  }
458  if (finalG > 255) {
459  gSrc = 255;
460  } else {
461  gSrc = finalG;
462  }
463  if (finalB > 255) {
464  bSrc = 255;
465  } else {
466  bSrc = finalB;
467  }
468  }
469 
470  if (!kBlendingEnabled) {
471  setPixelAt(pixel, _pbufFormat.ARGBToColor(aSrc, rSrc, gSrc, bSrc));
472  } else {
473  byte rDst, gDst, bDst, aDst;
474  _pbufFormat.colorToARGB(getPixelAt(pixel), aDst, rDst, gDst, bDst);
475  switch (_sourceBlendingFactor) {
476  case TGL_ZERO:
477  rSrc = gSrc = bSrc = 0;
478  break;
479  case TGL_ONE:
480  break;
481  case TGL_DST_COLOR:
482  rSrc = (rDst * rSrc) >> 8;
483  gSrc = (gDst * gSrc) >> 8;
484  bSrc = (bDst * bSrc) >> 8;
485  break;
486  case TGL_ONE_MINUS_DST_COLOR:
487  rSrc = (rSrc * (255 - rDst)) >> 8;
488  gSrc = (gSrc * (255 - gDst)) >> 8;
489  bSrc = (bSrc * (255 - bDst)) >> 8;
490  break;
491  case TGL_SRC_ALPHA:
492  rSrc = (rSrc * aSrc) >> 8;
493  gSrc = (gSrc * aSrc) >> 8;
494  bSrc = (bSrc * aSrc) >> 8;
495  break;
496  case TGL_ONE_MINUS_SRC_ALPHA:
497  rSrc = (rSrc * (255 - aSrc)) >> 8;
498  gSrc = (gSrc * (255 - aSrc)) >> 8;
499  bSrc = (bSrc * (255 - aSrc)) >> 8;
500  break;
501  case TGL_DST_ALPHA:
502  rSrc = (rSrc * aDst) >> 8;
503  gSrc = (gSrc * aDst) >> 8;
504  bSrc = (bSrc * aDst) >> 8;
505  break;
506  case TGL_ONE_MINUS_DST_ALPHA:
507  rSrc = (rSrc * (255 - aDst)) >> 8;
508  gSrc = (gSrc * (255 - aDst)) >> 8;
509  bSrc = (bSrc * (255 - aDst)) >> 8;
510  break;
511  default:
512  break;
513  }
514 
515  switch (_destinationBlendingFactor) {
516  case TGL_ZERO:
517  rDst = gDst = bDst = 0;
518  break;
519  case TGL_ONE:
520  break;
521  case TGL_DST_COLOR:
522  rDst = (rDst * rSrc) >> 8;
523  gDst = (gDst * gSrc) >> 8;
524  bDst = (bDst * bSrc) >> 8;
525  break;
526  case TGL_ONE_MINUS_DST_COLOR:
527  rDst = (rDst * (255 - rSrc)) >> 8;
528  gDst = (gDst * (255 - gSrc)) >> 8;
529  bDst = (bDst * (255 - bSrc)) >> 8;
530  break;
531  case TGL_SRC_ALPHA:
532  rDst = (rDst * aSrc) >> 8;
533  gDst = (gDst * aSrc) >> 8;
534  bDst = (bDst * aSrc) >> 8;
535  break;
536  case TGL_ONE_MINUS_SRC_ALPHA:
537  rDst = (rDst * (255 - aSrc)) >> 8;
538  gDst = (gDst * (255 - aSrc)) >> 8;
539  bDst = (bDst * (255 - aSrc)) >> 8;
540  break;
541  case TGL_DST_ALPHA:
542  rDst = (rDst * aDst) >> 8;
543  gDst = (gDst * aDst) >> 8;
544  bDst = (bDst * aDst) >> 8;
545  break;
546  case TGL_ONE_MINUS_DST_ALPHA:
547  rDst = (rDst * (255 - aDst)) >> 8;
548  gDst = (gDst * (255 - aDst)) >> 8;
549  bDst = (bDst * (255 - aDst)) >> 8;
550  break;
551  case TGL_SRC_ALPHA_SATURATE: {
552  int factor = aSrc < 1 - aDst ? aSrc : 1 - aDst;
553  rDst = (rDst * factor) >> 8;
554  gDst = (gDst * factor) >> 8;
555  bDst = (bDst * factor) >> 8;
556  }
557  break;
558  default:
559  break;
560  }
561  int finalR = rDst + rSrc;
562  int finalG = gDst + gSrc;
563  int finalB = bDst + bSrc;
564  if (finalR > 255) {
565  finalR = 255;
566  }
567  if (finalG > 255) {
568  finalG = 255;
569  }
570  if (finalB > 255) {
571  finalB = 255;
572  }
573  setPixelAt(pixel, _pbufFormat.RGBToColor(finalR, finalG, finalB));
574  }
575  }
576 
577 public:
578 
579  void clear(int clear_z, int z, int clear_color, int r, int g, int b,
580  bool clearStencil, int stencilValue);
581  void clearRegion(int x, int y, int w, int h, bool clearZ, int z,
582  bool clearColor, int r, int g, int b, bool clearStencil, int stencilValue);
583 
584  const Common::Rect &getClippingRectangle() const {
585  return _clipRectangle;
586  }
587 
588  void setupScissor(bool enable, const int (&scissor)[4], const Common::Rect *clippingRectangle) {
589  _clippingEnabled = enable || clippingRectangle;
590 
591  if (enable && clippingRectangle) {
592  _clipRectangle = clippingRectangle->findIntersectingRect(Common::Rect(
593  scissor[0],
594  // all viewport calculations are already flipped upside down
595  _pbufHeight - scissor[1] - scissor[3],
596  scissor[0] + scissor[2],
597  _pbufHeight - scissor[1]));
598  } else if (enable) {
599  _clipRectangle = Common::Rect(
600  scissor[0],
601  // all viewport calculations are already flipped upside down
602  _pbufHeight - scissor[1] - scissor[3],
603  scissor[0] + scissor[2],
604  _pbufHeight - scissor[1]);
605  } else if (clippingRectangle) {
606  _clipRectangle = *clippingRectangle;
607  } else {
608  _clipRectangle = Common::Rect(0, 0, _pbufWidth, _pbufHeight);
609  }
610  }
611 
612  void enableBlending(bool enable) {
613  _blendingEnabled = enable;
614  }
615 
616  void setBlendingFactors(int sFactor, int dFactor) {
617  _sourceBlendingFactor = sFactor;
618  _destinationBlendingFactor = dFactor;
619  }
620 
621  void enableAlphaTest(bool enable) {
622  _alphaTestEnabled = enable;
623  }
624 
625  void setAlphaTestFunc(int func, int ref) {
626  _alphaTestFunc = func;
627  _alphaTestRefVal = ref;
628  }
629 
630  void enableDepthTest(bool enable) {
631  _depthTestEnabled = enable;
632  }
633 
634  void setDepthFunc(int func) {
635  _depthFunc = func;
636  }
637 
638  void enableDepthWrite(bool enable) {
639  _depthWrite = enable;
640  }
641 
642  void enableStencilTest(bool enable) {
643  _stencilTestEnabled = enable;
644  }
645 
646  void setStencilWriteMask(uint stencilWriteMask) {
647  _stencilWriteMask = stencilWriteMask;
648  }
649 
650  void enablePolygonStipple(bool enable) {
651  _polygonStippleEnabled = enable;
652  }
653 
654  void setPolygonStipplePattern(const byte *stipple) {
655  _polygonStipplePattern = stipple;
656  }
657 
658  void enableTwoColorStipple(bool enable) {
659  _twoColorStippleEnabled = enable;
660  }
661 
662  void setStippleColor(int r, int g, int b) {
663  _stippleColor = RGB_TO_PIXEL(r, g, b);
664  }
665 
666  void setStencilTestFunc(int stencilFunc, byte stencilValue, byte stencilMask) {
667  _stencilTestFunc = stencilFunc;
668  _stencilRefVal = stencilValue;
669  _stencilMask = stencilMask;
670  }
671 
672  void setStencilOp(int stencilSfail, int stencilDpfail, int stencilDppass) {
673  _stencilSfail = stencilSfail;
674  _stencilDpfail = stencilDpfail;
675  _stencilDppass = stencilDppass;
676  }
677 
678  void setOffsetStates(int offsetStates) {
679  _offsetStates = offsetStates;
680  }
681 
682  void setOffsetFactor(float offsetFactor) {
683  _offsetFactor = offsetFactor;
684  }
685 
686  void setOffsetUnits(float offsetUnits) {
687  _offsetUnits = offsetUnits;
688  }
689 
690  void setTexture(const TexelBuffer *texture, uint wraps, uint wrapt) {
691  _currentTexture = texture;
692  _wrapS = wraps;
693  _wrapT = wrapt;
694  }
695 
696  void setTextureEnvironment(const GLTextureEnv *texEnv) {
697  _textureEnv = texEnv;
698  }
699 
700  void setTextureSizeAndMask(int textureSize, int textureSizeMask) {
701  _textureSize = textureSize;
702  _textureSizeMask = textureSizeMask;
703  }
704 
705  void setFogEnabled(bool enable) {
706  _fogEnabled = enable;
707  }
708 
709  void setFogColor(float colorR, float colorG, float colorB) {
710  _fogColorR = colorR;
711  _fogColorG = colorG;
712  _fogColorB = colorB;
713  }
714 
715 private:
716 
722  Buffer *genOffscreenBuffer();
723  void delOffscreenBuffer(Buffer *buffer);
724  void blitOffscreenBuffer(Buffer *buffer);
725  void selectOffscreenBuffer(Buffer *buffer);
726  void clearOffscreenBuffer(Buffer *buffer);
727 
728  template <bool kSmoothMode, bool kDepthWrite, bool kFogMode, bool kAlphaTestEnabled, bool kEnableScissor,
729  bool kBlendingEnabled, bool kStencilEnabled, bool kDepthTestEnabled>
730  void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2,
731  FrameBuffer::ColorMode kColorMode, bool kInterpZ,
732  bool kInterpST, bool kInterpSTZ, bool stippleEnable);
733 
734  template <bool kSmoothMode, bool kDepthWrite, bool kFogMode, bool kEnableAlphaTest, bool kEnableScissor,
735  bool kEnableBlending, bool kStencilEnabled>
736  void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2,
737  FrameBuffer::ColorMode colorMode, bool interpZ,
738  bool interpST, bool interpSTZ);
739 
740  template <bool kSmoothMode, bool kDepthWrite, bool kFogMode, bool kEnableAlphaTest, bool kEnableScissor,
741  bool kBlendingEnabled>
742  void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2,
743  FrameBuffer::ColorMode kColorMode, bool kInterpZ,
744  bool kInterpST, bool kInterpSTZ);
745 
746  template <bool kSmoothMode, bool kDepthWrite, bool kFogMode, bool kEnableAlphaTest, bool kEnableScissor>
747  void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2,
748  FrameBuffer::ColorMode kColorMode, bool kInterpZ,
749  bool kInterpST, bool kInterpSTZ);
750 
751  template <bool kSmoothMode, bool kDepthWrite, bool kFogMode, bool kEnableAlphaTest>
752  void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2,
753  FrameBuffer::ColorMode kColorMode, bool kInterpZ,
754  bool kInterpST, bool kInterpSTZ);
755 
756  template <bool kSmoothMode, bool kDepthWrite, bool kFogMode>
757  void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2,
758  FrameBuffer::ColorMode kColorMode, bool kInterpZ,
759  bool kInterpST, bool kInterpSTZ);
760 
761  template <bool kSmoothMode, bool kDepthWrite>
762  void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2,
763  FrameBuffer::ColorMode kColorMode, bool kInterpZ,
764  bool kInterpST, bool kInterpSTZ);
765 
766  template <bool kSmoothMode>
767  void fillTriangle(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2,
768  FrameBuffer::ColorMode kColorMode, bool kInterpZ,
769  bool kInterpST, bool kInterpSTZ);
770 
771  template <bool kSmoothMode, bool kDepthWrite>
772  void fillTriangleTextureMapping(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2,
773  bool kInterpZ, bool kInterpST, bool kInterpSTZ);
774 
775 public:
776 
777  void fillTriangleTextureMappingPerspectiveSmooth(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
778  void fillTriangleTextureMappingPerspectiveFlat(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
779  void fillTriangleDepthOnly(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
780  void fillTriangleFlat(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
781  void fillTriangleSmooth(ZBufferPoint *p0, ZBufferPoint *p1, ZBufferPoint *p2);
782 
783  void plot(ZBufferPoint *p);
784  void fillLine(ZBufferPoint *p1, ZBufferPoint *p2);
785  void fillLineZ(ZBufferPoint *p1, ZBufferPoint *p2);
786 
787 private:
788 
789  void fillLineFlatZ(ZBufferPoint *p1, ZBufferPoint *p2);
790  void fillLineInterpZ(ZBufferPoint *p1, ZBufferPoint *p2);
791  void fillLineFlat(ZBufferPoint *p1, ZBufferPoint *p2);
792  void fillLineInterp(ZBufferPoint *p1, ZBufferPoint *p2);
793 
794  template <bool kDepthWrite>
795  FORCEINLINE void putPixel(uint pixelOffset, int color, int x, int y, uint z);
796 
797  template <bool kDepthWrite, bool kEnableScissor>
798  FORCEINLINE void putPixel(uint pixelOffset, int color, int x, int y, uint z);
799 
800  template <bool kEnableScissor>
801  FORCEINLINE void putPixel(uint pixelOffset, int color, int x, int y);
802 
803  template <bool kInterpRGB, bool kInterpZ, bool kDepthWrite>
804  void drawLine(const ZBufferPoint *p1, const ZBufferPoint *p2);
805 
806  template <bool kInterpRGB, bool kInterpZ, bool kDepthWrite, bool kEnableScissor>
807  void drawLine(const ZBufferPoint *p1, const ZBufferPoint *p2);
808 
809  void applyTextureEnvironment(
810  int internalformat,
811  uint previousA, uint previousR, uint previousG, uint previousB,
812  byte &texA, byte &texR, byte &texG, byte &texB);
813 
814  // the same as GL_TEXTURE_ENV_MODE == GL_MODULATE as fast-path for the default mode
815  void applyModulation(
816  uint previousA, uint previousR, uint previousG, uint previousB,
817  byte &texA, byte &texR, byte &texG, byte &texB);
818 
819  Buffer _offscreenBuffer;
820  byte *_pbuf;
821  int _pbufWidth;
822  int _pbufHeight;
823  int _pbufPitch;
824  Graphics::PixelFormat _pbufFormat;
825  int _pbufBpp;
826 
827  uint *_zbuf;
828  byte *_sbuf;
829 
830  bool _enableStencil;
831  int _textureSize;
832  int _textureSizeMask;
833 
834  Common::Rect _clipRectangle;
835  bool _clippingEnabled;
836 
837  const TexelBuffer *_currentTexture;
838  const GLTextureEnv *_textureEnv;
839  uint _wrapS, _wrapT;
840  bool _blendingEnabled;
841  int _sourceBlendingFactor;
842  int _destinationBlendingFactor;
843  bool _alphaTestEnabled;
844  int _alphaTestFunc;
845  int _alphaTestRefVal;
846  bool _depthTestEnabled;
847  bool _depthWrite;
848  bool _stencilTestEnabled;
849  int _stencilTestFunc;
850  byte _stencilRefVal;
851  byte _stencilMask;
852  byte _stencilWriteMask;
853  int _stencilSfail;
854  int _stencilDpfail;
855  int _stencilDppass;
856 
857  bool _polygonStippleEnabled;
858  bool _twoColorStippleEnabled;
859  uint32 _stippleColor;
860  const byte *_polygonStipplePattern;
861  int _depthFunc;
862  int _offsetStates;
863  float _offsetFactor;
864  float _offsetUnits;
865  bool _fogEnabled;
866  float _fogColorR;
867  float _fogColorG;
868  float _fogColorB;
869 };
870 
871 // memory.c
872 void gl_free(void *p);
873 void *gl_malloc(int size);
874 void *gl_zalloc(int size);
875 void *gl_realloc(void *p, int size);
876 
877 } // end of namespace TinyGL
878 
879 #endif
Definition: surface.h:67
Definition: zbuffer.h:87
Definition: pixelformat.h:138
ConcreteRect findIntersectingRect(const ConcreteRect &r) const
Definition: rect.h:302
Definition: rect.h:524
void init(int16 width, int16 height, int16 pitch, void *pixels, const PixelFormat &format)
Graphics::Surface * convertTo(const PixelFormat &dstFormat, const byte *srcPalette=0, int srcPaletteCount=256, const byte *dstPalette=0, int dstPaletteCount=0, DitherMethod method=kDitherFloyd) const
Definition: colormasks.h:27
void NORETURN_PRE error(MSVC_PRINTF const char *s,...) GCC_PRINTF(1
Definition: texelbuffer.h:29
Definition: zbuffer.h:81
Definition: zbuffer.h:108
Definition: zdirtyrect.h:51