Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
alexbevi
GitHub Repository: alexbevi/BizHawk
Path: blob/master/psx/octoshock/video/surface.cpp
2 views
1
/* Mednafen - Multi-system Emulator
2
*
3
* This program is free software; you can redistribute it and/or modify
4
* it under the terms of the GNU General Public License as published by
5
* the Free Software Foundation; either version 2 of the License, or
6
* (at your option) any later version.
7
*
8
* This program is distributed in the hope that it will be useful,
9
* but WITHOUT ANY WARRANTY; without even the implied warranty of
10
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
11
* GNU General Public License for more details.
12
*
13
* You should have received a copy of the GNU General Public License
14
* along with this program; if not, write to the Free Software
15
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
16
*/
17
18
#include <string.h>
19
#include <assert.h>
20
#include <stdio.h>
21
#include <stdlib.h>
22
#include <math.h>
23
#include "octoshock.h"
24
#include "surface.h"
25
26
MDFN_PixelFormat::MDFN_PixelFormat()
27
{
28
bpp = 0;
29
colorspace = 0;
30
31
Rshift = 0;
32
Gshift = 0;
33
Bshift = 0;
34
Ashift = 0;
35
36
Rprec = 0;
37
Gprec = 0;
38
Bprec = 0;
39
Aprec = 0;
40
}
41
42
MDFN_PixelFormat::MDFN_PixelFormat(const unsigned int p_colorspace, const uint8 p_rs, const uint8 p_gs, const uint8 p_bs, const uint8 p_as)
43
{
44
bpp = 32;
45
colorspace = p_colorspace;
46
47
Rshift = p_rs;
48
Gshift = p_gs;
49
Bshift = p_bs;
50
Ashift = p_as;
51
52
Rprec = 8;
53
Gprec = 8;
54
Bprec = 8;
55
Aprec = 8;
56
}
57
58
MDFN_Surface::MDFN_Surface()
59
{
60
memset(&format, 0, sizeof(format));
61
62
pixels = NULL;
63
pixels8 = NULL;
64
pixels16 = NULL;
65
palette = NULL;
66
pixels_is_external = false;
67
pitchinpix = 0;
68
w = 0;
69
h = 0;
70
}
71
72
MDFN_Surface::MDFN_Surface(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf, const bool alloc_init_pixels)
73
{
74
Init(p_pixels, p_width, p_height, p_pitchinpix, nf, alloc_init_pixels);
75
}
76
77
#if 0
78
void MDFN_Surface::Resize(const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix)
79
{
80
void *ptr = (format.bpp == 16) ? pixels16 : pixels;
81
uint64 old_asize = ((uint64)pitchinpix * (format.bpp >> 3)) * h;
82
uint64 new_asize = ((uint64)p_pitchinpix * (format.bpp >> 3)) * p_height;
83
84
if(!(ptr = realloc(ptr, new_asize)))
85
throw MDFN_Error(ErrnoHolder(errno));
86
87
if(new_asize > old_asize)
88
memset((uint8*)ptr + old_asize, 0x00, new_asize - old_asize);
89
90
if(format.bpp == 16)
91
pixels16 = (uint16*)ptr;
92
else
93
pixels = (uint32*)ptr;
94
95
pitchinpix = p_pitchinpix;
96
w = p_width;
97
h = p_height;
98
}
99
#endif
100
101
void MDFN_Surface::Init(void *const p_pixels, const uint32 p_width, const uint32 p_height, const uint32 p_pitchinpix, const MDFN_PixelFormat &nf, const bool alloc_init_pixels)
102
{
103
void *rpix = NULL;
104
assert(nf.bpp == 8 || nf.bpp == 16 || nf.bpp == 32);
105
106
format = nf;
107
108
if(nf.bpp == 8)
109
{
110
//assert(!nf.Rshift && !nf.Gshift && !nf.Bshift && !nf.Ashift);
111
//assert(!nf.Rprec && !nf.Gprec && !nf.Bprec && !nf.Aprec);
112
}
113
else if(nf.bpp == 16)
114
{
115
assert(nf.Rprec && nf.Gprec && nf.Bprec && nf.Aprec);
116
}
117
else
118
{
119
assert((nf.Rshift + nf.Gshift + nf.Bshift + nf.Ashift) == 48);
120
assert(!((nf.Rshift | nf.Gshift | nf.Bshift | nf.Ashift) & 0x7));
121
122
format.Rprec = 8;
123
format.Gprec = 8;
124
format.Bprec = 8;
125
format.Aprec = 8;
126
}
127
128
pixels16 = NULL;
129
pixels8 = NULL;
130
pixels = NULL;
131
palette = NULL;
132
133
pixels_is_external = false;
134
135
if(p_pixels)
136
{
137
rpix = p_pixels;
138
pixels_is_external = true;
139
}
140
else
141
{
142
if(alloc_init_pixels)
143
rpix = calloc(1, p_pitchinpix * p_height * (nf.bpp / 8));
144
else
145
rpix = malloc(p_pitchinpix * p_height * (nf.bpp / 8));
146
147
if(!rpix)
148
{
149
//ErrnoHolder ene(errno);
150
151
throw "OLD ERROR";
152
//throw(MDFN_Error(ene.Errno(), "%s", ene.StrError()));
153
}
154
}
155
156
if(nf.bpp == 8)
157
{
158
if(!(palette = (MDFN_PaletteEntry*) calloc(sizeof(MDFN_PaletteEntry), 256)))
159
{
160
//ErrnoHolder ene(errno);
161
162
if(!pixels_is_external)
163
free(rpix);
164
165
throw "OLD ERROR";
166
//throw(MDFN_Error(ene.Errno(), "%s", ene.StrError()));
167
}
168
}
169
170
if(nf.bpp == 16)
171
pixels16 = (uint16 *)rpix;
172
else if(nf.bpp == 8)
173
pixels8 = (uint8 *)rpix;
174
else
175
pixels = (uint32 *)rpix;
176
177
w = p_width;
178
h = p_height;
179
180
pitchinpix = p_pitchinpix;
181
}
182
183
// When we're converting, only convert the w*h area(AKA leave the last part of the line, pitch32 - w, alone),
184
// for places where we store auxillary information there(graphics viewer in the debugger), and it'll be faster
185
// to boot.
186
void MDFN_Surface::SetFormat(const MDFN_PixelFormat &nf, bool convert)
187
{
188
if(format.bpp != 32 || nf.bpp != 32)
189
printf("%u->%u\n",format.bpp, nf.bpp);
190
191
assert(format.bpp == 8 || format.bpp == 16 || format.bpp == 32);
192
assert((nf.bpp == 8 && !convert) || nf.bpp == 16 || nf.bpp == 32);
193
194
if(nf.bpp == 8)
195
{
196
197
}
198
else if(nf.bpp == 16)
199
{
200
201
}
202
else
203
{
204
assert((nf.Rshift + nf.Gshift + nf.Bshift + nf.Ashift) == 48);
205
assert(!((nf.Rshift | nf.Gshift | nf.Bshift | nf.Ashift) & 0x7));
206
}
207
208
if(nf.bpp != format.bpp)
209
{
210
void *rpix = calloc(1, pitchinpix * h * (nf.bpp / 8));
211
void *oldpix;
212
213
if(nf.bpp == 8)
214
{
215
assert(!convert);
216
217
pixels8 = (uint8 *)rpix;
218
palette = (MDFN_PaletteEntry*)calloc(sizeof(MDFN_PaletteEntry), 256);
219
}
220
else if(nf.bpp == 16) // 32bpp or 8bpp to 16bpp
221
{
222
pixels16 = (uint16 *)rpix;
223
224
if(convert)
225
{
226
if(format.bpp == 8)
227
{
228
uint16 palconv[256];
229
230
for(unsigned i = 0; i < 256; i++)
231
{
232
uint8 r, g, b;
233
234
format.DecodePColor(palette[i], r, g, b);
235
palconv[i] = nf.MakeColor(r, g, b, 0);
236
}
237
238
puts("8bpp to 16bpp convert");
239
for(int y = 0; y < h; y++)
240
{
241
uint8 *srow = &pixels8[y * pitchinpix];
242
uint16 *drow = &pixels16[y * pitchinpix];
243
244
for(int x = 0; x < w; x++)
245
{
246
drow[x] = palconv[srow[x]];
247
}
248
}
249
}
250
else
251
{
252
puts("32bpp to 16bpp convert");
253
for(int y = 0; y < h; y++)
254
{
255
uint32 *srow = &pixels[y * pitchinpix];
256
uint16 *drow = &pixels16[y * pitchinpix];
257
258
for(int x = 0; x < w; x++)
259
{
260
uint32 c = srow[x];
261
int r, g, b, a;
262
263
DecodeColor(c, r, g, b, a);
264
drow[x] = nf.MakeColor(r, g, b, a);
265
}
266
}
267
}
268
}
269
}
270
else // 16bpp or 8bpp to 32bpp
271
{
272
pixels = (uint32 *)rpix;
273
274
if(convert)
275
{
276
if(format.bpp == 8)
277
{
278
uint32 palconv[256];
279
280
for(unsigned i = 0; i < 256; i++)
281
{
282
uint8 r, g, b;
283
284
format.DecodePColor(palette[i], r, g, b);
285
palconv[i] = nf.MakeColor(r, g, b, 0);
286
}
287
288
puts("8bpp to 32bpp convert");
289
for(int y = 0; y < h; y++)
290
{
291
uint8 *srow = &pixels8[y * pitchinpix];
292
uint32 *drow = &pixels[y * pitchinpix];
293
294
for(int x = 0; x < w; x++)
295
{
296
drow[x] = palconv[srow[x]];
297
}
298
}
299
}
300
else
301
{
302
puts("16bpp to 32bpp convert");
303
for(int y = 0; y < h; y++)
304
{
305
uint16 *srow = &pixels16[y * pitchinpix];
306
uint32 *drow = &pixels[y * pitchinpix];
307
308
for(int x = 0; x < w; x++)
309
{
310
uint32 c = srow[x];
311
int r, g, b, a;
312
313
DecodeColor(c, r, g, b, a);
314
drow[x] = nf.MakeColor(r, g, b, a);
315
}
316
}
317
}
318
}
319
}
320
321
switch(format.bpp)
322
{
323
default:
324
325
case 32: oldpix = pixels;
326
pixels = NULL;
327
break;
328
329
case 16: oldpix = pixels16;
330
pixels16 = NULL;
331
break;
332
333
case 8: oldpix = pixels8;
334
pixels8 = NULL;
335
if(palette)
336
{
337
free(palette);
338
palette = NULL;
339
}
340
break;
341
}
342
343
if(oldpix && !pixels_is_external)
344
free(oldpix);
345
346
pixels_is_external = false;
347
348
// We already handled surface conversion above.
349
convert = false;
350
}
351
352
if(convert)
353
{
354
if(format.bpp == 16)
355
{
356
// We should assert that surface->pixels is non-NULL even if we don't need to convert the surface, to catch more insidious bugs.
357
assert(pixels16);
358
359
if(memcmp(&format, &nf, sizeof(MDFN_PixelFormat)))
360
{
361
//puts("Converting");
362
for(int y = 0; y < h; y++)
363
{
364
uint16 *row = &pixels16[y * pitchinpix];
365
366
for(int x = 0; x < w; x++)
367
{
368
uint32 c = row[x];
369
int r, g, b, a;
370
371
DecodeColor(c, r, g, b, a);
372
row[x] = nf.MakeColor(r, g, b, a);
373
}
374
}
375
}
376
}
377
else
378
{
379
// We should assert that surface->pixels is non-NULL even if we don't need to convert the surface, to catch more insidious bugs.
380
assert(pixels);
381
382
if(memcmp(&format, &nf, sizeof(MDFN_PixelFormat)))
383
{
384
//puts("Converting");
385
for(int y = 0; y < h; y++)
386
{
387
uint32 *row = &pixels[y * pitchinpix];
388
389
for(int x = 0; x < w; x++)
390
{
391
uint32 c = row[x];
392
int r, g, b, a;
393
394
DecodeColor(c, r, g, b, a);
395
row[x] = nf.MakeColor(r, g, b, a);
396
}
397
}
398
}
399
}
400
}
401
format = nf;
402
}
403
404
void MDFN_Surface::Fill(uint8 r, uint8 g, uint8 b, uint8 a)
405
{
406
uint32 color = MakeColor(r, g, b, a);
407
408
if(format.bpp == 8)
409
{
410
assert(pixels8);
411
412
for(int32 i = 0; i < pitchinpix * h; i++)
413
pixels8[i] = color;
414
}
415
else if(format.bpp == 16)
416
{
417
assert(pixels16);
418
419
for(int32 i = 0; i < pitchinpix * h; i++)
420
pixels16[i] = color;
421
}
422
else
423
{
424
assert(pixels);
425
426
for(int32 i = 0; i < pitchinpix * h; i++)
427
pixels[i] = color;
428
}
429
}
430
431
MDFN_Surface::~MDFN_Surface()
432
{
433
if(!pixels_is_external)
434
{
435
if(pixels)
436
free(pixels);
437
if(pixels16)
438
free(pixels16);
439
if(pixels8)
440
free(pixels8);
441
if(palette)
442
free(palette);
443
}
444
}
445
446