Quake II RTX doxygen  1.0 dev
draw.c
Go to the documentation of this file.
1 /*
2 Copyright (C) 1997-2001 Id Software, Inc.
3 
4 This program is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 2 of the License, or
7 (at your option) any later version.
8 
9 This program is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13 
14 You should have received a copy of the GNU General Public License along
15 with this program; if not, write to the Free Software Foundation, Inc.,
16 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
17 */
18 
19 // draw.c
20 
21 #include "sw.h"
22 
23 #define STEP \
24  dst[0] = (dst[0] * (255 - src[3]) + src[2] * src[3]) >> 8; \
25  dst[1] = (dst[1] * (255 - src[3]) + src[1] * src[3]) >> 8; \
26  dst[2] = (dst[2] * (255 - src[3]) + src[0] * src[3]) >> 8; \
27  dst += VID_BYTES; \
28  src += TEX_BYTES;
29 
30 #define STEP_M \
31  tmp[0] = (src[0] * color.u8[0]) >> 8; \
32  tmp[1] = (src[1] * color.u8[1]) >> 8; \
33  tmp[2] = (src[2] * color.u8[2]) >> 8; \
34  tmp[3] = (src[3] * color.u8[3]) >> 8; \
35  dst[0] = (dst[0] * (255 - tmp[3]) + tmp[2] * tmp[3]) >> 8; \
36  dst[1] = (dst[1] * (255 - tmp[3]) + tmp[1] * tmp[3]) >> 8; \
37  dst[2] = (dst[2] * (255 - tmp[3]) + tmp[0] * tmp[3]) >> 8; \
38  dst += VID_BYTES; \
39  src += TEX_BYTES;
40 
41 #define STRETCH \
42  _src = src + (u >> 16) * TEX_BYTES; \
43  dst[0] = (dst[0] * (255 - _src[3]) + _src[2] * _src[3]) >> 8; \
44  dst[1] = (dst[1] * (255 - _src[3]) + _src[1] * _src[3]) >> 8; \
45  dst[2] = (dst[2] * (255 - _src[3]) + _src[0] * _src[3]) >> 8; \
46  dst += VID_BYTES; \
47  u += ustep;
48 
49 #define STRETCH_M \
50  _src = src + (u >> 16) * TEX_BYTES; \
51  tmp[0] = (_src[0] * color.u8[0]) >> 8; \
52  tmp[1] = (_src[1] * color.u8[1]) >> 8; \
53  tmp[2] = (_src[2] * color.u8[2]) >> 8; \
54  tmp[3] = (_src[3] * color.u8[3]) >> 8; \
55  dst[0] = (dst[0] * (255 - tmp[3]) + tmp[2] * tmp[3]) >> 8; \
56  dst[1] = (dst[1] * (255 - tmp[3]) + tmp[1] * tmp[3]) >> 8; \
57  dst[2] = (dst[2] * (255 - tmp[3]) + tmp[0] * tmp[3]) >> 8; \
58  dst += VID_BYTES; \
59  u += ustep;
60 
61 #define ROW1(DO) \
62  do { \
63  DO; \
64  } while (--count)
65 
66 #define ROW4(DO) \
67  do { \
68  DO; \
69  DO; \
70  DO; \
71  DO; \
72  \
73  count -= 4; \
74  } while (count)
75 
76 #define ROW8(DO) \
77  do { \
78  DO; \
79  DO; \
80  DO; \
81  DO; \
82  DO; \
83  DO; \
84  DO; \
85  DO; \
86  \
87  count -= 8; \
88  } while (count)
89 
90 typedef struct {
91  color_t colors[2];
92  clipRect_t clip;
93 } drawStatic_t;
94 
96 
97 float R_ClampScale(cvar_t *var)
98 {
99  if (var) {
100  Cvar_SetValue(var, 1.0f, FROM_CODE);
101  }
102  return 1.0f;
103 }
104 
105 void R_SetScale(float scale)
106 {
107 }
108 
109 void R_InitDraw(void)
110 {
111  memset(&draw, 0, sizeof(draw));
112  draw.colors[0].u32 = U32_WHITE;
113  draw.colors[1].u32 = U32_WHITE;
114  draw.clip.left = 0;
115  draw.clip.top = 0;
116  draw.clip.right = r_config.width;
117  draw.clip.bottom = r_config.height;
118 }
119 
120 void R_ClearColor(void)
121 {
122  draw.colors[0].u32 = U32_WHITE;
123  draw.colors[1].u32 = U32_WHITE;
124 }
125 
126 void R_SetAlpha(float alpha)
127 {
128  draw.colors[0].u8[3] = alpha * 255;
129  draw.colors[1].u8[3] = alpha * 255;
130 }
131 
132 void R_SetColor(uint32_t color)
133 {
134  draw.colors[0].u32 = color;
135  draw.colors[1].u8[3] = draw.colors[0].u8[3];
136 }
137 
138 void R_SetClipRect(const clipRect_t *clip)
139 {
140  if (!clip) {
141 clear:
142  draw.clip.left = 0;
143  draw.clip.top = 0;
144  draw.clip.right = r_config.width;
145  draw.clip.bottom = r_config.height;
146  return;
147  }
148 
149  draw.clip = *clip;
150 
151  if (draw.clip.left < 0)
152  draw.clip.left = 0;
153  if (draw.clip.top < 0)
154  draw.clip.top = 0;
155  if (draw.clip.right > r_config.width)
156  draw.clip.right = r_config.width;
157  if (draw.clip.bottom > r_config.height)
158  draw.clip.bottom = r_config.height;
159  if (draw.clip.right < draw.clip.left)
160  goto clear;
161  if (draw.clip.bottom < draw.clip.top)
162  goto clear;
163 }
164 
165 /*
166 =============
167 R_DrawStretchData
168 =============
169 */
170 static void R_DrawStretchData(int x, int y, int w, int h, int xx, int yy,
171  int ww, int hh, int pitch, byte *data, color_t color)
172 {
173  byte *srcpixels, *dstpixels, *dst, *src;
174  int v, u;
175  int ustep, vstep;
176  int skipv = 0, skipu = 0;
177  int width = w, height = h;
178  int count;
179  byte *_src;
180  int tmp[4];
181 
182  if (x < draw.clip.left) {
183  skipu = draw.clip.left - x;
184  w -= skipu;
185  x = draw.clip.left;
186  }
187  if (y < draw.clip.top) {
188  skipv = draw.clip.top - y;
189  h -= skipv;
190  y = draw.clip.top;
191  }
192 
193  if (x + w > draw.clip.right)
194  w = draw.clip.right - x;
195  if (y + h > draw.clip.bottom)
196  h = draw.clip.bottom - y;
197  if (w <= 0 || h <= 0)
198  return;
199 
200  srcpixels = data + yy * pitch + xx * TEX_BYTES;
201  dstpixels = vid.buffer + y * vid.rowbytes + x * VID_BYTES;
202 
203  vstep = hh * 0x10000 / height;
204 
205  v = skipv * vstep;
206  if (color.u32 == U32_WHITE) {
207  if (width == ww) {
208  dstpixels += skipu * VID_BYTES;
209  do {
210  src = &srcpixels[(v >> 16) * pitch];
211  dst = dstpixels;
212  count = w;
213 
214  if (!(w & 7)) {
215  ROW8(STEP);
216  } else if (!(w & 3)) {
217  ROW4(STEP);
218  } else {
219  ROW1(STEP);
220  }
221 
222  v += vstep;
223  dstpixels += vid.rowbytes;
224  } while (--h);
225  } else {
226  ustep = ww * 0x10000 / width;
227  skipu = skipu * ustep;
228  do {
229  src = &srcpixels[(v >> 16) * pitch];
230  dst = dstpixels;
231  count = w;
232 
233  u = skipu;
234  if (!(w & 7)) {
235  ROW8(STRETCH);
236  } else if (!(w & 3)) {
237  ROW4(STRETCH);
238  } else {
239  ROW1(STRETCH);
240  }
241 
242  v += vstep;
243  dstpixels += vid.rowbytes;
244  } while (--h);
245  }
246  } else {
247  if (width == ww) {
248  dstpixels += skipu * VID_BYTES;
249  do {
250  src = &srcpixels[(v >> 16) * pitch];
251  dst = dstpixels;
252  count = w;
253 
254  if (!(w & 7)) {
255  ROW8(STEP_M);
256  } else if (!(w & 3)) {
257  ROW4(STEP_M);
258  } else {
259  ROW1(STEP_M);
260  }
261 
262  v += vstep;
263  dstpixels += vid.rowbytes;
264  } while (--h);
265  } else {
266  ustep = ww * 0x10000 / width;
267  skipu = skipu * ustep;
268  do {
269  src = &srcpixels[(v >> 16) * pitch];
270  dst = dstpixels;
271  count = w;
272 
273  u = skipu;
274  if (!(w & 7)) {
275  ROW8(STRETCH_M);
276  } else if (!(w & 3)) {
277  ROW4(STRETCH_M);
278  } else {
279  ROW1(STRETCH_M);
280  }
281 
282  v += vstep;
283  dstpixels += vid.rowbytes;
284  } while (--h);
285  }
286  }
287 }
288 
289 /*
290 =============
291 R_DrawFixedData
292 =============
293 */
294 static void R_DrawFixedData(int x, int y, int w, int h,
295  int pitch, byte *data, color_t color)
296 {
297  byte *srcpixels, *dstpixels;
298  byte *dst, *src;
299  int skipv = 0, skipu = 0;
300  int count;
301  int tmp[4];
302 
303  if (x < draw.clip.left) {
304  skipu = draw.clip.left - x;
305  w -= skipu;
306  x = draw.clip.left;
307  }
308  if (y < draw.clip.top) {
309  skipv = draw.clip.top - y;
310  h -= skipv;
311  y = draw.clip.top;
312  }
313 
314  if (x + w > draw.clip.right)
315  w = draw.clip.right - x;
316  if (y + h > draw.clip.bottom)
317  h = draw.clip.bottom - y;
318  if (w <= 0 || h <= 0)
319  return;
320 
321  srcpixels = data + skipv * pitch + skipu * TEX_BYTES;
322  dstpixels = vid.buffer + y * vid.rowbytes + x * VID_BYTES;
323 
324  if (color.u32 == U32_WHITE) {
325  if (!(w & 7)) {
326  do {
327  src = srcpixels;
328  dst = dstpixels;
329  count = w; ROW8(STEP);
330  srcpixels += pitch;
331  dstpixels += vid.rowbytes;
332  } while (--h);
333  } else if (!(w & 3)) {
334  do {
335  src = srcpixels;
336  dst = dstpixels;
337  count = w; ROW4(STEP);
338  srcpixels += pitch;
339  dstpixels += vid.rowbytes;
340  } while (--h);
341  } else {
342  do {
343  src = srcpixels;
344  dst = dstpixels;
345  count = w; ROW1(STEP);
346  srcpixels += pitch;
347  dstpixels += vid.rowbytes;
348  } while (--h);
349  }
350  } else {
351  if (!(w & 7)) {
352  do {
353  src = srcpixels;
354  dst = dstpixels;
355  count = w; ROW8(STEP_M);
356  srcpixels += pitch;
357  dstpixels += vid.rowbytes;
358  } while (--h);
359  } else if (!(w & 3)) {
360  do {
361  src = srcpixels;
362  dst = dstpixels;
363  count = w; ROW4(STEP_M);
364  srcpixels += pitch;
365  dstpixels += vid.rowbytes;
366  } while (--h);
367  } else {
368  do {
369  src = srcpixels;
370  dst = dstpixels;
371  count = w; ROW1(STEP_M);
372  srcpixels += pitch;
373  dstpixels += vid.rowbytes;
374  } while (--h);
375  }
376  }
377 }
378 
379 /*
380 =============
381 R_DrawStretchPic
382 =============
383 */
384 void R_DrawStretchPic(int x, int y, int w, int h, qhandle_t pic)
385 {
386  image_t *image = IMG_ForHandle(pic);
387 
388  if (w == image->upload_width && h == image->upload_height)
389  R_DrawFixedData(x, y, image->upload_width, image->upload_height,
390  image->upload_width * TEX_BYTES, image->pixels[0], draw.colors[0]);
391  else
392  R_DrawStretchData(x, y, w, h, 0, 0, image->upload_width, image->upload_height,
393  image->upload_width * TEX_BYTES, image->pixels[0], draw.colors[0]);
394 }
395 
396 /*
397 =============
398 R_DrawStretcpic
399 =============
400 */
401 void R_DrawPic(int x, int y, qhandle_t pic)
402 {
403  image_t *image = IMG_ForHandle(pic);
404 
405  if (image->width == image->upload_width && image->height == image->upload_height)
406  R_DrawFixedData(x, y, image->upload_width, image->upload_height,
407  image->upload_width * TEX_BYTES, image->pixels[0], draw.colors[0]);
408  else
409  R_DrawStretchData(x, y, image->width, image->height, 0, 0, image->upload_width, image->upload_height,
410  image->upload_width * TEX_BYTES, image->pixels[0], draw.colors[0]);
411 }
412 
413 static inline void draw_char(int x, int y, int flags, int ch, image_t *image)
414 {
415  int x2, y2;
416  byte *data;
417 
418  if ((ch & 127) == 32)
419  return;
420 
421  if (flags & UI_ALTCOLOR)
422  ch |= 0x80;
423 
424  if (flags & UI_XORCOLOR)
425  ch ^= 0x80;
426 
427  x2 = (ch & 15) * CHAR_WIDTH;
428  y2 = ((ch >> 4) & 15) * CHAR_HEIGHT;
429  data = image->pixels[0] + y2 * image->upload_width * TEX_BYTES + x2 * TEX_BYTES;
430 
431  R_DrawFixedData(x, y, CHAR_WIDTH, CHAR_HEIGHT, image->upload_width * TEX_BYTES, data, draw.colors[ch >> 7]);
432 }
433 
434 void R_DrawChar(int x, int y, int flags, int ch, qhandle_t font)
435 {
436  image_t *image;
437 
438  if (!font)
439  return;
440 
441  image = IMG_ForHandle(font);
442  if (image->upload_width != 128 || image->upload_height != 128)
443  return;
444 
445  draw_char(x, y, flags, ch & 255, image);
446 }
447 
448 /*
449 ===============
450 R_DrawString
451 ===============
452 */
453 int R_DrawString(int x, int y, int flags, size_t maxChars,
454  const char *string, qhandle_t font)
455 {
456  image_t *image;
457 
458  if (!font)
459  return x;
460 
461  image = IMG_ForHandle(font);
462  if (image->upload_width != 128 || image->upload_height != 128)
463  return x;
464 
465  while (maxChars-- && *string) {
466  byte c = *string++;
467  draw_char(x, y, flags, c, image);
468  x += CHAR_WIDTH;
469  }
470 
471  return x;
472 }
473 
474 /*
475 =============
476 R_TileClear
477 
478 This repeats a 64*64 tile graphic to fill the screen around a sized down
479 refresh window.
480 =============
481 */
482 void R_TileClear(int x, int y, int w, int h, qhandle_t pic)
483 {
484  int i, j;
485  byte *psrc;
486  byte *pdest;
487  image_t *image;
488  int x2;
489 
490  if (!pic)
491  return;
492 
493  if (x < 0) {
494  w += x;
495  x = 0;
496  }
497  if (y < 0) {
498  h += y;
499  y = 0;
500  }
501  if (x + w > vid.width)
502  w = vid.width - x;
503  if (y + h > vid.height)
504  h = vid.height - y;
505  if (w <= 0 || h <= 0)
506  return;
507 
508  image = IMG_ForHandle(pic);
509  if (image->upload_width != 64 || image->upload_height != 64)
510  return;
511 
512  x2 = x + w;
513  pdest = vid.buffer + y * vid.rowbytes;
514  for (i = 0; i < h; i++, pdest += vid.rowbytes) {
515  psrc = image->pixels[0] + 64 * TEX_BYTES * ((i + y) & 63);
516  for (j = x; j < x2; j++) {
517  pdest[j * VID_BYTES + 0] = psrc[(j & 63) * TEX_BYTES + 2];
518  pdest[j * VID_BYTES + 1] = psrc[(j & 63) * TEX_BYTES + 1];
519  pdest[j * VID_BYTES + 2] = psrc[(j & 63) * TEX_BYTES + 0];
520  }
521  }
522 }
523 
524 
525 /*
526 =============
527 R_DrawFill
528 
529 Fills a box of pixels with a single color
530 =============
531 */
532 void R_DrawFill8(int x, int y, int w, int h, int c)
533 {
534  byte *dest;
535  int u, v;
536  color_t color;
537 
538  if (x + w > vid.width)
539  w = vid.width - x;
540  if (y + h > vid.height)
541  h = vid.height - y;
542  if (x < 0) {
543  w += x;
544  x = 0;
545  }
546  if (y < 0) {
547  h += y;
548  y = 0;
549  }
550  if (w < 0 || h < 0)
551  return;
552 
553  color.u32 = d_8to24table[c & 0xff];
554 
555  dest = vid.buffer + y * vid.rowbytes + x * VID_BYTES;
556  for (v = 0; v < h; v++, dest += vid.rowbytes) {
557  for (u = 0; u < w; u++) {
558  dest[u * VID_BYTES + 0] = color.u8[2];
559  dest[u * VID_BYTES + 1] = color.u8[1];
560  dest[u * VID_BYTES + 2] = color.u8[0];
561  }
562  }
563 }
564 
565 void R_DrawFill32(int x, int y, int w, int h, uint32_t c)
566 {
567  byte *dest;
568  int u, v;
569  color_t color;
570  int alpha, one_minus_alpha;
571  fixed8_t pre[3];
572 
573  if (x + w > vid.width)
574  w = vid.width - x;
575  if (y + h > vid.height)
576  h = vid.height - y;
577  if (x < 0) {
578  w += x;
579  x = 0;
580  }
581  if (y < 0) {
582  h += y;
583  y = 0;
584  }
585  if (w < 0 || h < 0)
586  return;
587 
588  color.u32 = c;
589 
590  alpha = color.u8[3];
591  one_minus_alpha = 255 - alpha;
592 
593  pre[0] = color.u8[0] * alpha;
594  pre[1] = color.u8[1] * alpha;
595  pre[2] = color.u8[2] * alpha;
596 
597  dest = vid.buffer + y * vid.rowbytes + x * VID_BYTES;
598  for (v = 0; v < h; v++, dest += vid.rowbytes) {
599  for (u = 0; u < w; u++) {
600  dest[u * VID_BYTES + 0] = (dest[u * VID_BYTES + 0] * one_minus_alpha + pre[2]) >> 8;
601  dest[u * VID_BYTES + 1] = (dest[u * VID_BYTES + 1] * one_minus_alpha + pre[1]) >> 8;
602  dest[u * VID_BYTES + 2] = (dest[u * VID_BYTES + 2] * one_minus_alpha + pre[0]) >> 8;
603  }
604  }
605 }
STEP_M
#define STEP_M
Definition: draw.c:30
R_TileClear
void R_TileClear(int x, int y, int w, int h, qhandle_t pic)
Definition: draw.c:482
R_ClampScale
float R_ClampScale(cvar_t *var)
Definition: draw.c:97
R_SetClipRect
void R_SetClipRect(const clipRect_t *clip)
Definition: draw.c:138
height
static int height
Definition: physical_sky.c:39
viddef_t::buffer
pixel_t * buffer
Definition: sw.h:124
image_t
struct image_s image_t
Definition: material.h:27
R_ClearColor
void R_ClearColor(void)
Definition: draw.c:120
TEX_BYTES
#define TEX_BYTES
Definition: sw.h:50
viddef_t::width
int width
Definition: sw.h:127
drawStatic_t::colors
color_t colors[2]
Definition: gl.h:402
viddef_t::height
int height
Definition: sw.h:128
d_8to24table
uint32_t d_8to24table[256]
Definition: images.c:654
R_DrawStretchPic
void R_DrawStretchPic(int x, int y, int w, int h, qhandle_t pic)
Definition: draw.c:384
R_DrawStretchData
static void R_DrawStretchData(int x, int y, int w, int h, int xx, int yy, int ww, int hh, int pitch, byte *data, color_t color)
Definition: draw.c:170
R_SetAlpha
void R_SetAlpha(float alpha)
Definition: draw.c:126
draw
drawStatic_t draw
Definition: draw.c:21
ROW1
#define ROW1(DO)
Definition: draw.c:61
width
static int width
Definition: physical_sky.c:38
ROW4
#define ROW4(DO)
Definition: draw.c:66
viddef_t::rowbytes
int rowbytes
Definition: sw.h:125
R_DrawFill8
void R_DrawFill8(int x, int y, int w, int h, int c)
Definition: draw.c:532
STEP
#define STEP
Definition: draw.c:23
sw.h
Cvar_SetValue
void Cvar_SetValue(cvar_t *var, float value, from_t from)
Definition: cvar.c:487
draw_char
static void draw_char(int x, int y, int flags, int ch, image_t *image)
Definition: draw.c:413
R_DrawFill32
void R_DrawFill32(int x, int y, int w, int h, uint32_t c)
Definition: draw.c:565
STRETCH
#define STRETCH
Definition: draw.c:41
drawStatic_t::clip
clipRect_t clip
Definition: draw.c:92
VID_BYTES
#define VID_BYTES
Definition: sw.h:49
c
statCounters_t c
Definition: main.c:30
R_DrawString
int R_DrawString(int x, int y, int flags, size_t maxChars, const char *string, qhandle_t font)
Definition: draw.c:453
R_DrawFixedData
static void R_DrawFixedData(int x, int y, int w, int h, int pitch, byte *data, color_t color)
Definition: draw.c:294
drawStatic_t
Definition: gl.h:401
STRETCH_M
#define STRETCH_M
Definition: draw.c:49
R_SetColor
void R_SetColor(uint32_t color)
Definition: draw.c:132
ROW8
#define ROW8(DO)
Definition: draw.c:76
R_InitDraw
void R_InitDraw(void)
Definition: draw.c:109
R_SetScale
void R_SetScale(float scale)
Definition: draw.c:105
R_DrawChar
void R_DrawChar(int x, int y, int flags, int ch, qhandle_t font)
Definition: draw.c:434
color
static vec4_t color
Definition: mesh.c:33
IMG_ForHandle
image_t * IMG_ForHandle(qhandle_t h)
Definition: images.c:1156
vid
viddef_t vid
Definition: main.c:22
r_config
refcfg_t r_config
Definition: refresh.c:401
R_DrawPic
void R_DrawPic(int x, int y, qhandle_t pic)
Definition: draw.c:401