/[pcsx2_0.9.7]/trunk/plugins/zzogl-pg/opengl/ZZoglShoots.cpp
ViewVC logotype

Contents of /trunk/plugins/zzogl-pg/opengl/ZZoglShoots.cpp

Parent Directory Parent Directory | Revision Log Revision Log


Revision 280 - (show annotations) (download)
Thu Dec 23 12:02:12 2010 UTC (9 years, 1 month ago) by william
File size: 16250 byte(s)
re-commit (had local access denied errors when committing)
1 /* ZZ Open GL graphics plugin
2 * Copyright (c)2009-2010 zeydlitz@gmail.com, arcum42@gmail.com
3 * Based on Zerofrog's ZeroGS KOSMOS (c)2005-2008
4 *
5 * This program is free software; you can redistribute it and/or modify
6 * it under the terms of the GNU General Public License as published by
7 * the Free Software Foundation; either version 2 of the License, or
8 * (at your option) any later version.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program; if not, write to the Free Software
17 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA
18 */
19
20 // Texture and avi saving to file functions
21
22 //------------------ Includes
23 #include "Util.h"
24 #if defined(_WIN32)
25 # include <windows.h>
26 # include <aviUtil.h>
27 # include "resource.h"
28 #endif
29 #include <stdlib.h>
30
31 #include "targets.h"
32 #include "Mem.h"
33 #include "ZZoglShoots.h"
34
35 // AVI Capture
36 int s_avicapturing = 0;
37 bool g_bMakeSnapshot = false;
38
39 extern "C"
40 {
41 #ifdef _WIN32
42 # define XMD_H
43 # undef FAR
44 #define HAVE_BOOLEAN
45 #endif
46
47 #include "jpeglib.h"
48 }
49
50 //------------------ Defines
51 #define TGA_FILE_NAME_MAX_LENGTH 20
52 #define MAX_NUMBER_SAVED_TGA 200
53
54 //Windows have no snprintf
55 #if defined(_WIN32)
56 # define snprintf sprintf_s
57 #endif
58 //------------------ Constants
59
60 //------------------ Global Variables
61 int TexNumber = 0;
62 int s_aviinit = 0;
63
64 string strSnapshot;
65
66 //------------------ Code
67
68 // Set variables need to made a snapshoot when it's possible
69 void SaveSnapshot(const char* filename)
70 {
71 g_bMakeSnapshot = true;
72 strSnapshot = filename;
73 }
74
75 // Save curent renderer in jpeg or TGA format
76 bool SaveRenderTarget(const char* filename, int width, int height, int jpeg)
77 {
78 bool bflip = height < 0;
79 height = abs(height);
80 vector<u32> data(width*height);
81 glReadPixels(0, 0, width, height, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
82
83 if (glGetError() != GL_NO_ERROR) return false;
84
85 if (bflip)
86 {
87 // swap scanlines
88 vector<u32> scanline(width);
89
90 for (int i = 0; i < height / 2; ++i)
91 {
92 memcpy(&scanline[0], &data[i * width], width * 4);
93 memcpy(&data[i * width], &data[(height - i - 1) * width], width * 4);
94 memcpy(&data[(height - i - 1) * width], &scanline[0], width * 4);
95 }
96 }
97
98 if (jpeg) return SaveJPEG(filename, width, height, &data[0], 70);
99
100 return SaveTGA(filename, width, height, &data[0]);
101 }
102
103 // Save selected texture as TGA
104 bool SaveTexture(const char* filename, u32 textarget, u32 tex, int width, int height)
105 {
106 vector<u32> data(width*height);
107 glBindTexture(textarget, tex);
108 glGetTexImage(textarget, 0, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
109
110 if (glGetError() != GL_NO_ERROR) return false;
111
112 return SaveTGA(filename, width, height, &data[0]);
113 }
114
115 // save image as JPEG
116 bool SaveJPEG(const char* filename, int image_width, int image_height, const void* pdata, int quality)
117 {
118 u8* image_buffer = new u8[image_width * image_height * 3];
119 u8* psrc = (u8*)pdata;
120
121 // input data is rgba format, so convert to rgb
122 u8* p = image_buffer;
123
124 for (int i = 0; i < image_height; ++i)
125 {
126 for (int j = 0; j < image_width; ++j)
127 {
128 p[0] = psrc[0];
129 p[1] = psrc[1];
130 p[2] = psrc[2];
131 p += 3;
132 psrc += 4;
133 }
134 }
135
136 /* This struct contains the JPEG compression parameters and pointers to
137 * working space (which is allocated as needed by the JPEG library).
138 * It is possible to have several such structures, representing multiple
139 * compression/decompression processes, in existence at once. We refer
140 * to any one struct (and its associated working data) as a "JPEG object".
141 */
142
143 struct jpeg_compress_struct cinfo;
144
145 /* This struct represents a JPEG error handler. It is declared separately
146 * because applications often want to supply a specialized error handler
147 * (see the second half of this file for an example). But here we just
148 * take the easy way out and use the standard error handler, which will
149 * print a message on stderr and call exit() if compression fails.
150 * Note that this struct must live as long as the main JPEG parameter
151 * struct, to avoid dangling-pointer problems.
152 */
153
154 struct jpeg_error_mgr jerr;
155
156 /* More stuff */
157 FILE * outfile; /* target file */
158
159 JSAMPROW row_pointer[1]; /* pointer to JSAMPLE row[s] */
160
161 int row_stride; /* physical row width in image buffer */
162
163 /* Step 1: allocate and initialize JPEG compression object */
164
165 /* We have to set up the error handler first, in case the initialization
166 * step fails. (Unlikely, but it could happen if you are out of memory.)
167 * This routine fills in the contents of struct jerr, and returns jerr's
168 * address which we place into the link field in cinfo.
169 */
170 cinfo.err = jpeg_std_error(&jerr);
171
172 /* Now we can initialize the JPEG compression object. */
173 jpeg_create_compress(&cinfo);
174
175 /* Step 2: specify data destination (eg, a file) */
176 /* Note: steps 2 and 3 can be done in either order. */
177
178 /* Here we use the library-supplied code to send compressed data to a
179 * stdio stream. You can also write your own code to do something else.
180 * VERY IMPORTANT: use "b" option to fopen() if you are on a machine that
181 * requires it in order to write binary files.
182 */
183 if ((outfile = fopen(filename, "wb")) == NULL)
184 {
185 fprintf(stderr, "can't open %s\n", filename);
186 exit(1);
187 }
188
189 jpeg_stdio_dest(&cinfo, outfile);
190
191 /* Step 3: set parameters for compression */
192
193 /* First we supply a description of the input image.
194 * Four fields of the cinfo struct must be filled in:
195 */
196 cinfo.image_width = image_width; /* image width and height, in pixels */
197 cinfo.image_height = image_height;
198 cinfo.input_components = 3; /* # of color components per pixel */
199 cinfo.in_color_space = JCS_RGB; /* colorspace of input image */
200 /* Now use the library's routine to set default compression parameters.
201 * (You must set at least cinfo.in_color_space before calling this,
202 * since the defaults depend on the source color space.)
203 */
204 jpeg_set_defaults(&cinfo);
205 /* Now you can set any non-default parameters you wish to.
206 * Here we just illustrate the use of quality (quantization table) scaling:
207 */
208 jpeg_set_quality(&cinfo, quality, true /* limit to baseline-JPEG values */);
209
210 /* Step 4: Start compressor */
211
212 /* true ensures that we will write a complete interchange-JPEG file.
213 * Pass true unless you are very sure of what you're doing.
214 */
215 jpeg_start_compress(&cinfo, true);
216
217 /* Step 5: while (scan lines remain to be written) */
218 /* jpeg_write_scanlines(...); */
219
220 /* Here we use the library's state variable cinfo.next_scanline as the
221 * loop counter, so that we don't have to keep track ourselves.
222 * To keep things simple, we pass one scanline per call; you can pass
223 * more if you wish, though.
224 */
225 row_stride = image_width * 3; /* JSAMPLEs per row in image_buffer */
226
227 while (cinfo.next_scanline < cinfo.image_height)
228 {
229 /* jpeg_write_scanlines expects an array of pointers to scanlines.
230 * Here the array is only one element long, but you could pass
231 * more than one scanline at a time if that's more convenient.
232 */
233 row_pointer[0] = & image_buffer[cinfo.next_scanline * row_stride];
234 (void) jpeg_write_scanlines(&cinfo, row_pointer, 1);
235 }
236
237 /* Step 6: Finish compression */
238
239 jpeg_finish_compress(&cinfo);
240
241 /* After finish_compress, we can close the output file. */
242 fclose(outfile);
243
244 /* Step 7: release JPEG compression object */
245
246 /* This is an important step since it will release a good deal of memory. */
247 jpeg_destroy_compress(&cinfo);
248
249 delete image_buffer;
250
251 /* And we're done! */
252 return true;
253 }
254
255 #if defined(_MSC_VER)
256 # pragma pack(push, 1)
257 #endif
258
259 // This is the defenition of TGA header. We need it to function bellow
260
261 struct TGA_HEADER
262 {
263 u8 identsize; // size of ID field that follows 18 u8 header (0 usually)
264 u8 colourmaptype; // type of colour map 0=none, 1=has palette
265 u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed
266
267 s16 colourmapstart; // first colour map entry in palette
268 s16 colourmaplength; // number of colours in palette
269 u8 colourmapbits; // number of bits per palette entry 15,16,24,32
270
271 s16 xstart; // image x origin
272 s16 ystart; // image y origin
273 s16 width; // image width in pixels
274 s16 height; // image height in pixels
275 u8 bits; // image bits per pixel 8,16,24,32
276 u8 descriptor; // image descriptor bits (vh flip bits)
277
278 // pixel data follows header
279 #if defined(_MSC_VER)
280 };
281
282 # pragma pack(pop)
283 # else
284 }
285
286 __attribute__((packed));
287 #endif
288
289 // Save image as TGA
290 bool SaveTGA(const char* filename, int width, int height, void* pdata)
291 {
292 int err = 0;
293 TGA_HEADER hdr;
294 FILE* f = fopen(filename, "wb");
295
296 if (f == NULL) return false;
297
298 assert(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18);
299
300 memset(&hdr, 0, sizeof(hdr));
301
302 hdr.imagetype = 2;
303 hdr.bits = 32;
304 hdr.width = width;
305 hdr.height = height;
306 hdr.descriptor |= 8 | (1 << 5); // 8bit alpha, flip vertical
307
308 err = fwrite(&hdr, sizeof(hdr), 1, f);
309 err = fwrite(pdata, width * height * 4, 1, f);
310
311 fclose(f);
312
313 return true;
314 }
315
316 // AVI capture stuff
317 // AVI start -- set needed global variables
318 void StartCapture()
319 {
320 if (conf.captureAvi()) return;
321 if (!s_aviinit)
322 {
323 #ifdef _WIN32
324 START_AVI("zerogs.avi");
325 #else // linux
326 //TODO
327 #endif
328 s_aviinit = 1;
329 }
330 else
331 {
332 ZZLog::Error_Log("Continuing from previous capture.");
333 }
334
335 s_avicapturing = 1;
336 conf.setCaptureAvi(true);
337 ZZLog::Warn_Log("Started recording zerogs.avi.");
338
339 }
340
341 // Stop.
342 void StopCapture()
343 {
344 if (!conf.captureAvi()) return;
345 s_avicapturing = 0;
346 conf.setCaptureAvi(false);
347 ZZLog::Warn_Log("Stopped recording.");
348 }
349
350 // And capture frame does not work on linux.
351 void CaptureFrame()
352 {
353 if ((!s_avicapturing) || (!s_aviinit)) return;
354
355 vector<u32> data(GLWin.backbuffer.w * GLWin.backbuffer.h);
356 glReadPixels(0, 0, GLWin.backbuffer.w, GLWin.backbuffer.h, GL_RGBA, GL_UNSIGNED_BYTE, &data[0]);
357
358 if (glGetError() != GL_NO_ERROR) return;
359
360 #ifdef _WIN32
361 int fps = SMODE1->CMOD == 3 ? 50 : 60;
362
363 bool bSuccess = ADD_FRAME_FROM_DIB_TO_AVI("AAAA", fps, GLWin.backbuffer.w, GLWin.backbuffer.h, 32, &data[0]);
364
365 if (!bSuccess)
366 {
367 s_avicapturing = 0;
368 STOP_AVI();
369 ZZAddMessage("Failed to create avi");
370 return;
371 }
372
373 #else // linux
374 //TODO
375 #endif // _WIN32
376 }
377
378 // It's nearly the same as save texture
379 void
380 SaveTex(tex0Info* ptex, int usevid)
381 {
382 vector<u32> data(ptex->tw*ptex->th);
383 vector<u8> srcdata;
384
385 u32* dst = &data[0];
386 u8* psrc = g_pbyGSMemory;
387
388 CMemoryTarget* pmemtarg = NULL;
389
390 if (usevid)
391 {
392 pmemtarg = g_MemTargs.GetMemoryTarget(*ptex, 0);
393 assert(pmemtarg != NULL);
394
395 glBindTexture(GL_TEXTURE_RECTANGLE_NV, pmemtarg->ptex->tex);
396 srcdata.resize(4 * pmemtarg->texW * pmemtarg->texH);
397
398 // FIXME strangely this function call seem to crash pcsx2 on atelier of iris 1
399 // Note: fmt is GL_UNSIGNED_SHORT_1_5_5_5_REV
400 glGetTexImage(GL_TEXTURE_RECTANGLE_NV, 0, GL_RGBA, pmemtarg->fmt, &srcdata[0]);
401
402 u32 offset = MemorySize(pmemtarg->realy);
403
404 if (ptex->psm == PSMT8)
405 offset *= CLUT_PIXEL_SIZE(ptex->cpsm);
406 else if (ptex->psm == PSMT4)
407 offset *= CLUT_PIXEL_SIZE(ptex->cpsm) * 2;
408
409 psrc = &srcdata[0] - offset;
410 }
411
412 for (int i = 0; i < ptex->th; ++i)
413 {
414 for (int j = 0; j < ptex->tw; ++j)
415 {
416 u32 u = 0;
417 u32 addr;
418
419 switch (ptex->psm)
420 {
421 case PSMCT32:
422 addr = getPixelAddress32(j, i, ptex->tbp0, ptex->tbw);
423 if (addr * 4 < MEMORY_END)
424 u = readPixel32(psrc, j, i, ptex->tbp0, ptex->tbw);
425 else
426 u = 0;
427 break;
428
429 case PSMCT24:
430 addr = getPixelAddress24(j, i, ptex->tbp0, ptex->tbw);
431 if (addr * 4 < MEMORY_END)
432 u = readPixel24(psrc, j, i, ptex->tbp0, ptex->tbw);
433 else
434 u = 0;
435 break;
436
437 case PSMCT16:
438 addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw);
439 if (addr * 2 < MEMORY_END)
440 {
441 u = readPixel16(psrc, j, i, ptex->tbp0, ptex->tbw);
442 u = RGBA16to32(u);
443 }
444 else
445 {
446 u = 0;
447 }
448 break;
449
450 case PSMCT16S:
451 addr = getPixelAddress16(j, i, ptex->tbp0, ptex->tbw);
452 if (addr * 2 < MEMORY_END)
453 {
454 u = readPixel16S(psrc, j, i, ptex->tbp0, ptex->tbw);
455 u = RGBA16to32(u);
456 }
457 else
458 {
459 u = 0;
460 }
461 break;
462
463 case PSMT8:
464 addr = getPixelAddress8(j, i, ptex->tbp0, ptex->tbw);
465 if (addr < MEMORY_END)
466 {
467 if (usevid)
468 {
469 if (PSMT_IS32BIT(ptex->cpsm))
470 u = *(u32*)(psrc + 4 * addr);
471 else
472 u = RGBA16to32(*(u16*)(psrc + 2 * addr));
473 }
474 else
475 {
476 u = readPixel8(psrc, j, i, ptex->tbp0, ptex->tbw);
477 }
478 }
479 else
480 {
481 u = 0;
482 }
483 break;
484
485 case PSMT4:
486 addr = getPixelAddress4(j, i, ptex->tbp0, ptex->tbw);
487 if (addr < 2*MEMORY_END)
488 {
489 if (usevid)
490 {
491 if (PSMT_IS32BIT(ptex->cpsm))
492 u = *(u32*)(psrc + 4 * addr);
493 else
494 u = RGBA16to32(*(u16*)(psrc + 2 * addr));
495 }
496 else
497 {
498 u = readPixel4(psrc, j, i, ptex->tbp0, ptex->tbw);
499 }
500 }
501 else
502 {
503 u = 0;
504 }
505
506 break;
507
508 case PSMT8H:
509 addr = getPixelAddress8H(j, i, ptex->tbp0, ptex->tbw);
510 if (4*addr < MEMORY_END)
511 {
512 if (usevid)
513 {
514 if (PSMT_IS32BIT(ptex->cpsm))
515 u = *(u32*)(psrc + 4 * addr);
516 else
517 u = RGBA16to32(*(u16*)(psrc + 2 * addr));
518 }
519 else
520 {
521 u = readPixel8H(psrc, j, i, ptex->tbp0, ptex->tbw);
522 }
523 }
524 else
525 {
526 u = 0;
527 }
528 break;
529
530 case PSMT4HL:
531 addr = getPixelAddress4HL(j, i, ptex->tbp0, ptex->tbw);
532 if (4*addr < MEMORY_END)
533 {
534 if (usevid)
535 {
536 if (PSMT_IS32BIT(ptex->cpsm))
537 u = *(u32*)(psrc + 4 * addr);
538 else
539 u = RGBA16to32(*(u16*)(psrc + 2 * addr));
540 }
541 else
542 {
543 u = readPixel4HL(psrc, j, i, ptex->tbp0, ptex->tbw);
544 }
545 }
546 else
547 {
548 u = 0;
549 }
550 break;
551
552 case PSMT4HH:
553 addr = getPixelAddress4HH(j, i, ptex->tbp0, ptex->tbw);
554 if (4*addr < MEMORY_END)
555 {
556 if (usevid)
557 {
558 if (PSMT_IS32BIT(ptex->cpsm))
559 u = *(u32*)(psrc + 4 * addr);
560 else
561 u = RGBA16to32(*(u16*)(psrc + 2 * addr));
562 }
563 else
564 {
565 u = readPixel4HH(psrc, j, i, ptex->tbp0, ptex->tbw);
566 }
567 }
568 else
569 {
570 u = 0;
571 }
572 break;
573
574 case PSMT32Z:
575 addr = getPixelAddress32Z(j, i, ptex->tbp0, ptex->tbw);
576 if (4*addr < MEMORY_END)
577 u = readPixel32Z(psrc, j, i, ptex->tbp0, ptex->tbw);
578 else
579 u = 0;
580 break;
581
582 case PSMT24Z:
583 addr = getPixelAddress24Z(j, i, ptex->tbp0, ptex->tbw);
584 if (4*addr < MEMORY_END)
585 u = readPixel24Z(psrc, j, i, ptex->tbp0, ptex->tbw);
586 else
587 u = 0;
588 break;
589
590 case PSMT16Z:
591 addr = getPixelAddress16Z(j, i, ptex->tbp0, ptex->tbw);
592 if (2*addr < MEMORY_END)
593 u = readPixel16Z(psrc, j, i, ptex->tbp0, ptex->tbw);
594 else
595 u = 0;
596 break;
597
598 case PSMT16SZ:
599 addr = getPixelAddress16SZ(j, i, ptex->tbp0, ptex->tbw);
600 if (2*addr < MEMORY_END)
601 u = readPixel16SZ(psrc, j, i, ptex->tbp0, ptex->tbw);
602 else
603 u = 0;
604 break;
605
606 default:
607 assert(0);
608 }
609
610 *dst++ = u;
611 }
612 }
613
614 char Name[TGA_FILE_NAME_MAX_LENGTH];
615
616 snprintf(Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber);
617 SaveTGA(Name, ptex->tw, ptex->th, &data[0]);
618
619 TexNumber++;
620 if (TexNumber > MAX_NUMBER_SAVED_TGA) TexNumber = 0;
621 }
622
623
624 // Do the save texture and return file name of it
625 // Do not forget to call free(), other wise there would be memory leak!
626 char* NamedSaveTex(tex0Info* ptex, int usevid)
627 {
628 SaveTex(ptex, usevid);
629
630 char* Name = (char*)malloc(TGA_FILE_NAME_MAX_LENGTH);
631 snprintf(Name, TGA_FILE_NAME_MAX_LENGTH, "Tex.%d.tga", TexNumber);
632
633 return Name;
634 }
635
636 // Special function, which is safe to call from any other file, without aviutils problems.
637 void Stop_Avi()
638 {
639 #ifdef _WIN32
640 STOP_AVI();
641 #else
642 // Does not support yet
643 #endif
644 }
645
646 void Delete_Avi_Capture()
647 {
648 if (s_aviinit)
649 {
650 StopCapture();
651 Stop_Avi();
652 ZZLog::Error_Log("zerogs.avi stopped.");
653 s_aviinit = 0;
654 }
655 }

  ViewVC Help
Powered by ViewVC 1.1.22