UltraGrid
UltraGrid Low-Latency High-Resolution Transmission System
Loading...
Searching...
No Matches
dxt_encoder.c
Go to the documentation of this file.
1
27#ifdef HAVE_CONFIG_H
28#include "config.h"
29#include "config_unix.h"
30#endif
31#include "dxt_encoder.h"
32#include "dxt_util.h"
33#include "dxt_glsl.h"
34#if defined __APPLE__
35#include <Availability.h>
36#if defined __MAC_10_11
37#define GL_DO_NOT_WARN_IF_MULTI_GL_VERSION_HEADERS_INCLUDED
38#include <OpenGL/gl3.h>
39#endif // defined __MAC_10_11
40#else // ! defined __APPLE__
41#include <GL/glew.h>
42#endif
43
44#if defined __APPLE__ && !defined __MAC_10_11
45#define glGenFramebuffers glGenFramebuffersEXT
46#define glBindFramebuffer glBindFramebufferEXT
47#define GL_FRAMEBUFFER GL_FRAMEBUFFER_EXT
48#define glFramebufferTexture2D glFramebufferTexture2DEXT
49#define glDeleteFramebuffers glDeleteFramebuffersEXT
50#define GL_FRAMEBUFFER_COMPLETE GL_FRAMEBUFFER_COMPLETE_EXT
51#define glCheckFramebufferStatus glCheckFramebufferStatusEXT
52#endif
53
54#ifdef HAVE_GPUPERFAPI
55#include "GPUPerfAPI.h"
56static void WriteSession( gpa_uint32 currentWaitSessionID, const char* filename );
57#endif
58
59#include <string.h>
60
61static GLfloat points[] = { -1.0f, -1.0f, 0.0f, 1.0f,
62 1.0f, -1.0f, 0.0f, 1.0f,
63 -1.0f, 1.0f, 0.0f, 1.0f,
64 /* second triangle */
65 1.0f, -1.0f, 0.0f, 1.0f,
66 -1.0f, 1.0f, 0.0f, 1.0f,
67 1.0f, 1.0f, 0.0f, 1.0f
68};
69
70const int FORMAT_RGB = 0;
71const int FORMAT_YUV = 1;
72
75{
76 unsigned int legacy:1;
77
78 // DXT type
80
81 // Width in pixels
82 int width;
83
84 // Height in pixels
85 int height;
86
87 // Format
89
90 // Texture id
91 GLuint texture_id;
92
93#ifdef USE_PBO_DXT_ENCODER
94 // PBO
95 GLuint pbo_in;
96 GLuint pbo_out;
97#endif
98
99 // Compressed texture
101
103
104 // Framebuffer
105 GLuint fbo_id;
106
107 // Program and shader handles
111
115 GLuint fbo444_id;
116
120 GLuint g_vao;
121 GLuint g_vao_422;
122
127
128#ifdef HAVE_GPUPERFAPI
129 gpa_uint32 numRequiredPasses;
130 gpa_uint32 sessionID;
131 gpa_uint32 currentWaitSessionID;
132#endif
133#ifdef RTDXT_DEBUG
134 GLuint queries[4];
135#endif
136};
137
139
141 encoder->yuv422_to_444_fp = 0;
142 if(encoder->legacy) {
143 encoder->yuv422_to_444_fp = dxt_shader_create_from_source(fp_yuv422_to_yuv_444_legacy, GL_FRAGMENT_SHADER);
144 } else {
145 encoder->yuv422_to_444_fp = dxt_shader_create_from_source(fp_yuv422_to_yuv_444, GL_FRAGMENT_SHADER);
146 }
147
148 if ( encoder->yuv422_to_444_fp == 0) {
149 fprintf(stderr, "Failed to compile YUV422->YUV444 fragment program!\n");
150 return 0;
151 }
152
153 if(encoder->legacy) {
154 encoder->yuv422_to_444_vp = dxt_shader_create_from_source(vp_compress_legacy, GL_VERTEX_SHADER);
155 } else {
156 encoder->yuv422_to_444_vp = dxt_shader_create_from_source(vp_compress, GL_VERTEX_SHADER);
157 }
158
159 encoder->yuv422_to_444_program = glCreateProgram();
160 glAttachShader(encoder->yuv422_to_444_program, encoder->yuv422_to_444_fp);
161 glAttachShader(encoder->yuv422_to_444_program, encoder->yuv422_to_444_vp);
162 glLinkProgram(encoder->yuv422_to_444_program);
163
164 if(!encoder->legacy) {
165#if ! defined __APPLE__ || defined __MAC_10_11
166 GLint g_vertexLocation;
167 GLuint g_vertices;
168
169 // ToDo:
170 glGenVertexArrays(1, &encoder->g_vao_422);
171
172 // ToDo:
173 glBindVertexArray(encoder->g_vao_422);
174
175 // http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml
176 g_vertexLocation = glGetAttribLocation(encoder->yuv422_to_444_program, "position");
177
178 // http://www.opengl.org/sdk/docs/man/xhtml/glGenBuffers.xml
179 glGenBuffers(1, &g_vertices);
180
181 // http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml
182 glBindBuffer(GL_ARRAY_BUFFER, g_vertices);
183
184 // http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml
185 //glBufferData(GL_ARRAY_BUFFER, 3 * 4 * sizeof(GLfloat), (GLfloat*) points, GL_STATIC_DRAW);
186 glBufferData(GL_ARRAY_BUFFER, 8 * 4 * sizeof(GLfloat), (GLfloat*) points, GL_STATIC_DRAW);
187
188 // http://www.opengl.org/sdk/docs/man/xhtml/glUseProgram.xml
189 glUseProgram(encoder->yuv422_to_444_program);
190
191 // http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribPointer.xml
192 glVertexAttribPointer(g_vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
193
194 // http://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml
195 glEnableVertexAttribArray(g_vertexLocation);
196
197 glBindFragDataLocation(encoder->yuv422_to_444_program, 0, "colorOut");
198
199 glUseProgram(0);
200#endif
201 }
202
203 char log[32768];
204 glGetProgramInfoLog(encoder->yuv422_to_444_program, 32768, NULL, (GLchar*)log);
205 if ( strlen(log) > 0 )
206 printf("Link Log: %s\n", log);
207
208 glGenTextures(1, &encoder->texture_yuv422);
209 glBindTexture(GL_TEXTURE_2D, encoder->texture_yuv422);
210 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
211 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
212 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
213 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
214 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, encoder->width / 2, encoder->height,
215 0, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, NULL);
216
217 glUseProgram(encoder->yuv422_to_444_program);
218 glUniform1i(glGetUniformLocation(encoder->yuv422_to_444_program, "image"), 0);
219 glUniform1f(glGetUniformLocation(encoder->yuv422_to_444_program, "imageWidth"),
220 (GLfloat) encoder->width);
221
222 // Create fbo
223 glGenFramebuffers(1, &encoder->fbo444_id);
224 return 1;
225}
226
227
229struct dxt_encoder*
231{
232 struct dxt_encoder* encoder = (struct dxt_encoder*)malloc(sizeof(struct dxt_encoder));
233
234#ifndef HAVE_MACOSX
235 glewExperimental = GL_TRUE;
236 GLenum err = glewInit();
237 assert(err == GLEW_OK);
238#endif
239
240 if ( encoder == NULL )
241 return NULL;
242 encoder->type = type;
243 encoder->width = width;
244 encoder->height = height;
245 encoder->format = format;
246 encoder->legacy = legacy;
247
248 if(legacy) {
249 glEnable(GL_TEXTURE_2D);
250 }
251
252 //glEnable(GL_TEXTURE_2D);
253#ifdef HAVE_GPUPERFAPI
254 GPA_EnableAllCounters();
255#endif
256
257 glGenFramebuffers(1, &encoder->fbo_id);
258 glBindFramebuffer(GL_FRAMEBUFFER, encoder->fbo_id);
259
260#ifdef USE_PBO_DXT_ENCODER
261 int bpp;
262 if(format == DXT_FORMAT_RGB) {
263 bpp = 3;
264 } else {
265 bpp = 4;
266 }
267
268 glGenBuffersARB(1, &encoder->pbo_in); //Allocate PBO
269 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, encoder->pbo_in);
270 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB,width*height*bpp,0,GL_STREAM_DRAW_ARB);
271 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, 0);
272
273 glGenBuffersARB(1, &encoder->pbo_out); //Allocate PBO
274 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, encoder->pbo_out);
275 glBufferDataARB(GL_PIXEL_PACK_BUFFER_ARB, ((width + 3) / 4 * 4) * ((height + 3) / 4 * 4) / (encoder->type == DXT_TYPE_DXT5_YCOCG ? 1 : 2), 0, GL_STREAM_READ_ARB);
276 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
277
278#endif
279
280 GLuint fbo_tex;
281 glGenTextures(1, &fbo_tex);
282 glBindTexture(GL_TEXTURE_2D, fbo_tex);
283 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
284 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
285 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
286 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
287 if ( encoder->type == DXT_TYPE_DXT5_YCOCG )
288 glTexImage2D(GL_TEXTURE_2D, 0 , GL_RGBA32UI_EXT, (encoder->width + 3) / 4 * 4, (encoder->height + 3) / 4, 0, GL_RGBA_INTEGER_EXT, GL_INT, 0);
289 else
290 glTexImage2D(GL_TEXTURE_2D, 0 , GL_RGBA16UI_EXT, (encoder->width + 3) / 4 * 4, (encoder->height + 3) / 4, 0, GL_RGBA_INTEGER_EXT, GL_INT, 0);
291 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, fbo_tex, 0);
292 glBindFramebuffer(GL_FRAMEBUFFER, 0);
293
294 // Create program [display] and its shader
295 encoder->program_compress = glCreateProgram();
296 // Create fragment shader from file
297 encoder->shader_fragment_compress = 0;
298 if ( encoder->type == DXT_TYPE_DXT5_YCOCG ) {
299 if(encoder->legacy) {
301 encoder->shader_fragment_compress = dxt_shader_create_from_source(fp_compress_dxt5ycocg_yuv_legacy, GL_FRAGMENT_SHADER);
302 } else {
303 encoder->shader_fragment_compress = dxt_shader_create_from_source(fp_compress_dxt5ycocg_legacy, GL_FRAGMENT_SHADER);
304 }
305 } else {
307 encoder->shader_fragment_compress = dxt_shader_create_from_source(fp_compress_dxt5ycocg_yuv, GL_FRAGMENT_SHADER);
308 } else {
309 encoder->shader_fragment_compress = dxt_shader_create_from_source(fp_compress_dxt5ycocg, GL_FRAGMENT_SHADER);
310 }
311 }
312 } else {
314 encoder->shader_fragment_compress = dxt_shader_create_from_source(encoder->legacy ? fp_compress_dxt1_yuv_legacy : fp_compress_dxt1_yuv, GL_FRAGMENT_SHADER);
315 } else if (((format == DXT_FORMAT_YUV422 || format == DXT_FORMAT_YUV) && encoder->type == DXT_TYPE_DXT1_YUV) ||
317 encoder->shader_fragment_compress = dxt_shader_create_from_source(encoder->legacy ? fp_compress_dxt1_legacy : fp_compress_dxt1, GL_FRAGMENT_SHADER);
318 } else {
319 fprintf(stderr, "RGB(A) to DXT1_YUV is not supported!\n");
320 }
321 }
322 if ( encoder->shader_fragment_compress == 0 ) {
323 fprintf(stderr, "Failed to compile fragment compress program!\n");
324 free(encoder);
325 return NULL;
326 }
327 // Create vertex shader from file
328 encoder->shader_vertex_compress = 0;
329 if(encoder->legacy) {
330 encoder->shader_vertex_compress = dxt_shader_create_from_source(vp_compress_legacy, GL_VERTEX_SHADER);
331 } else {
332 encoder->shader_vertex_compress = dxt_shader_create_from_source(vp_compress, GL_VERTEX_SHADER);
333 }
334 if ( encoder->shader_vertex_compress == 0 ) {
335 fprintf(stderr, "Failed to compile vertex compress program!\n");
336 free(encoder);
337 return NULL;
338 }
339 // Attach shader to program and link the program
340 glAttachShader(encoder->program_compress, encoder->shader_fragment_compress);
341 glAttachShader(encoder->program_compress, encoder->shader_vertex_compress);
342 glLinkProgram(encoder->program_compress);
343
344 char log[32768];
345 glGetProgramInfoLog(encoder->program_compress, 32768, NULL, (GLchar*)log);
346 if ( strlen(log) > 0 )
347 printf("Link Log: %s\n", log);
348
349
350 glGenTextures(1, &encoder->texture_id);
351 glBindTexture(GL_TEXTURE_2D, encoder->texture_id);
352 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
353 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
354 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
355 glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
356 if(format == DXT_FORMAT_RGB) {
357 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, encoder->width, encoder->height, 0, GL_RGB, GL_BYTE, NULL);
358 } else {
359 glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, encoder->width, encoder->height, 0, GL_RGBA, GL_UNSIGNED_BYTE, NULL);
360 }
361
362 //glActiveTexture(GL_TEXTURE0);
363
367 free(encoder);
368 return NULL;
369 }
370 }
371
372 glBindTexture(GL_TEXTURE_2D, encoder->texture_id);
373 //glClear(GL_COLOR_BUFFER_BIT);
374
375 glViewport(0, 0, (encoder->width + 3) / 4, encoder->height / 4);
376 glDisable(GL_DEPTH_TEST);
377
378 // User compress program and set image size parameters
379 glUseProgram(encoder->program_compress);
380//glBindFragDataLocation(encoder->program_compress, 0, "colorInt");
381 glUniform1i(glGetUniformLocation(encoder->program_compress, "image"), 0);
382
384 glUniform1i(glGetUniformLocation(encoder->program_compress, "imageFormat"), FORMAT_YUV);
385 } else {
386 glUniform1i(glGetUniformLocation(encoder->program_compress, "imageFormat"), FORMAT_RGB);
387 }
388 glUniform2f(glGetUniformLocation(encoder->program_compress, "imageSize"), encoder->width, (encoder->height + 3) / 4 * 4);
389 glUniform1f(glGetUniformLocation(encoder->program_compress, "textureWidth"), (encoder->width + 3) / 4 * 4);
390
391 if(!encoder->legacy) {
392#if ! defined __APPLE__ || defined __MAC_10_11
393 GLint g_vertexLocation;
394
395 // ToDo:
396 glGenVertexArrays(1, &encoder->g_vao);
397
398 // ToDo:
399 glBindVertexArray(encoder->g_vao);
400
401 // http://www.opengl.org/sdk/docs/man/xhtml/glGetAttribLocation.xml
402 g_vertexLocation = glGetAttribLocation(encoder->program_compress, "position");
403
404 // http://www.opengl.org/sdk/docs/man/xhtml/glGenBuffers.xml
405 glGenBuffers(1, &encoder->g_vertices);
406
407 // http://www.opengl.org/sdk/docs/man/xhtml/glBindBuffer.xml
408 glBindBuffer(GL_ARRAY_BUFFER, encoder->g_vertices);
409
410 // http://www.opengl.org/sdk/docs/man/xhtml/glBufferData.xml
411 //glBufferData(GL_ARRAY_BUFFER, 3 * 4 * sizeof(GLfloat), (GLfloat*) points, GL_STATIC_DRAW);
412 glBufferData(GL_ARRAY_BUFFER, 8 * 4 * sizeof(GLfloat), (GLfloat*) points, GL_STATIC_DRAW);
413
414 // http://www.opengl.org/sdk/docs/man/xhtml/glUseProgram.xml
415 //glUseProgram(g_program.program);
416
417 // http://www.opengl.org/sdk/docs/man/xhtml/glVertexAttribPointer.xml
418 glVertexAttribPointer(g_vertexLocation, 4, GL_FLOAT, GL_FALSE, 0, 0);
419
420 // http://www.opengl.org/sdk/docs/man/xhtml/glEnableVertexAttribArray.xml
421 glEnableVertexAttribArray(g_vertexLocation);
422
423 glBindFragDataLocation(encoder->program_compress, 0, "colorOut");
424#endif
425 }
426
427 // Render to framebuffer
428 glBindFramebuffer(GL_FRAMEBUFFER, encoder->fbo_id);
429
430#ifdef HAVE_GPUPERFAPI
431 GPA_BeginSession( &encoder->sessionID );
432 GPA_GetPassCount( &encoder->numRequiredPasses );
433 encoder->currentWaitSessionID = 0;
434#endif
435#ifdef RTDXT_DEBUG
436 glGenQueries(4, encoder->queries);
437#endif
438
439 return encoder;
440}
441
443int
444dxt_encoder_buffer_allocate(struct dxt_encoder* encoder, unsigned char** image_compressed, int* image_compressed_size)
445{
446 int size = 0;
447 if ( encoder->type == DXT_TYPE_DXT5_YCOCG )
448 size = (encoder->width / 4) * (encoder->height / 4) * 4 * sizeof(int);
449 else if ( encoder->type == DXT_TYPE_DXT1 )
450 size = (encoder->width / 4) * (encoder->height / 4) * 2 * sizeof(int);
451 else
452 assert(0);
453
454 *image_compressed = (unsigned char*)malloc(size);
455 if ( *image_compressed == NULL )
456 return -1;
457
458 if ( image_compressed_size != NULL )
459 *image_compressed_size = size;
460
461 return 0;
462}
463
465int
466dxt_encoder_compress(struct dxt_encoder* encoder, DXT_IMAGE_TYPE* image, unsigned char* image_compressed)
467{
468#ifdef RTDXT_DEBUG
469 glBeginQuery(GL_TIME_ELAPSED_EXT, encoder->queries[0]);
470#endif
471#ifdef RTDXT_DEBUG_HOST
472 TIMER_INIT();
473
474 TIMER_START();
475#endif
476#ifdef HAVE_GPUPERFAPI
477 GPA_BeginPass();
478 GPA_BeginSample(0);
479#endif
480#ifdef USE_PBO_DXT_ENCODER
481 GLubyte *ptr;
482#endif
483
484 int data_size = encoder->width * encoder->height;
485 switch(encoder->format) {
487 data_size *= 2;
488 break;
489 case DXT_FORMAT_RGB:
490 data_size *= 3;
491 break;
492 case DXT_FORMAT_RGBA:
493 case DXT_FORMAT_YUV:
494 data_size *= 4;
495 break;
496 }
497
498 switch(encoder->format) {
500 glBindFramebuffer(GL_FRAMEBUFFER, encoder->fbo444_id);
501 glFramebufferTexture2D(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0_EXT, GL_TEXTURE_2D, encoder->texture_id, 0);
502 glBindTexture(GL_TEXTURE_2D, encoder->texture_yuv422);
503
504 glPushAttrib(GL_VIEWPORT_BIT);
505 glViewport( 0, 0, encoder->width, encoder->height);
506
507#ifdef USE_PBO_DXT_ENCODER
508 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, encoder->pbo_in); // current pbo
509 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width / 2, encoder->height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, 0);
510 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, data_size, 0, GL_STREAM_DRAW_ARB);
511 ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
512 if(ptr)
513 {
514 // update data directly on the mapped buffer
515 memcpy(ptr, image, data_size);
516 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer
517 }
518#else
519 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width / 2, encoder->height, GL_RGBA, GL_UNSIGNED_INT_8_8_8_8_REV, image);
520#endif
521 glUseProgram(encoder->yuv422_to_444_program);
522#ifdef RTDXT_DEBUG
523 glEndQuery(GL_TIME_ELAPSED_EXT);
524 glBeginQuery(GL_TIME_ELAPSED_EXT, encoder->queries[1]);
525#endif
526#ifdef HAVE_GPUPERFAPI
527 GPA_EndSample();
528 GPA_BeginSample(1);
529#endif
530
531 if(encoder->legacy) {
532 glBegin(GL_QUADS);
533 glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
534 glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0);
535 glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
536 glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0);
537 glEnd();
538 } else {
539#if ! defined __APPLE__ || defined __MAC_10_11
540 // Compress
541 glBindVertexArray(encoder->g_vao_422);
542 //glDrawElements(GL_TRIANGLE_STRIP, sizeof(m_quad.indices) / sizeof(m_quad.indices[0]), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
543 glDrawArrays(GL_TRIANGLES, 0, 6);
544 glBindVertexArray(0);
545#endif
546 }
547
548 glPopAttrib();
549 /* there is some problem with restoring viewport state (Mac OS Lion, OpenGL 3.2) */
550 glViewport( 0, 0, (encoder->width + 3) / 4, encoder->height / 4);
551
552 //glBindFramebufferEXT(GL_FRAMEBUFFER_EXT, 0);
553
554 glUseProgram(encoder->program_compress);
555 glBindFramebuffer(GL_FRAMEBUFFER, encoder->fbo_id);
556 glBindTexture(GL_TEXTURE_2D, encoder->texture_id);
557
558 //gl_check_error();
559 break;
560 case DXT_FORMAT_YUV:
561 case DXT_FORMAT_RGBA:
562 glBindTexture(GL_TEXTURE_2D, encoder->texture_id);
563#ifdef USE_PBO_DXT_ENCODER
564 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, encoder->pbo_in); // current pbo
565 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGBA, DXT_IMAGE_GL_TYPE, 0);
566 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, data_size, 0, GL_STREAM_DRAW_ARB);
567 ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
568 if(ptr)
569 {
570 // update data directly on the mapped buffer
571 memcpy(ptr, image, data_size);
572 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer
573 }
574#else
575 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGBA, DXT_IMAGE_GL_TYPE, image);
576#endif
577
578 break;
579 case DXT_FORMAT_RGB:
580 glBindTexture(GL_TEXTURE_2D, encoder->texture_id);
581#ifdef USE_PBO_DXT_ENCODER
582 glBindBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, encoder->pbo_in); // current pbo
583 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGB, GL_UNSIGNED_BYTE, 0);
584 glBufferDataARB(GL_PIXEL_UNPACK_BUFFER_ARB, data_size, 0, GL_STREAM_DRAW_ARB);
585 ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB, GL_WRITE_ONLY_ARB);
586 if(ptr)
587 {
588 // update data directly on the mapped buffer
589 memcpy(ptr, image, data_size);
590 glUnmapBufferARB(GL_PIXEL_UNPACK_BUFFER_ARB); // release pointer to mapping buffer
591 }
592#else
593 glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, encoder->width, encoder->height, GL_RGB, GL_UNSIGNED_BYTE, image);
594#endif
595 break;
596 }
597#ifdef RTDXT_DEBUG
598 glEndQuery(GL_TIME_ELAPSED_EXT);
599 glBeginQuery(GL_TIME_ELAPSED_EXT, encoder->queries[2]);
600#endif
601#ifdef RTDXT_DEBUG_HOST
602 glFinish();
603 TIMER_STOP_PRINT("Tex Load (+->444): ");
604 TIMER_START();
605#endif
606
607#ifdef HAVE_GPUPERFAPI
608 GPA_EndSample();
609 GPA_BeginSample(2);
610#endif
611
612 return dxt_encoder_compress_texture(encoder, encoder->texture_id, image_compressed);
613}
614
615
616int
617dxt_encoder_compress_texture(struct dxt_encoder* encoder, int texture, unsigned char* image_compressed)
618{
619#ifdef USE_PBO_DXT_ENCODER
620 GLubyte *ptr;
621#endif
622
623 glBindTexture(GL_TEXTURE_2D, texture);
624
625 glDrawBuffer(GL_COLOR_ATTACHMENT0_EXT);
626 assert(GL_FRAMEBUFFER_COMPLETE == glCheckFramebufferStatus(GL_FRAMEBUFFER));
627
628 glClearColor(1,0,0,1);
629 glClear(GL_COLOR_BUFFER_BIT);
630
631 if(encoder->legacy) {
632 glBegin(GL_QUADS);
633 glTexCoord2f(0.0, 0.0); glVertex2f(-1.0, -1.0);
634 glTexCoord2f(1.0, 0.0); glVertex2f(1.0, -1.0);
635 glTexCoord2f(1.0, 1.0); glVertex2f(1.0, 1.0);
636 glTexCoord2f(0.0, 1.0); glVertex2f(-1.0, 1.0);
637 glEnd();
638 } else {
639#if ! defined __APPLE__ || defined __MAC_10_11
640 // Compress
641 glBindVertexArray(encoder->g_vao);
642 //glDrawElements(GL_TRIANGLE_STRIP, sizeof(m_quad.indices) / sizeof(m_quad.indices[0]), GL_UNSIGNED_SHORT, BUFFER_OFFSET(0));
643 glDrawArrays(GL_TRIANGLES, 0, 6);
644 glBindVertexArray(0);
645#endif
646 }
647#ifdef HAVE_GPUPERFAPI
648 GPA_EndSample();
649 GPA_BeginSample(3);
650#endif
651#ifdef RTDXT_DEBUG
652 glEndQuery(GL_TIME_ELAPSED_EXT);
653 glBeginQuery(GL_TIME_ELAPSED_EXT, encoder->queries[3]);
654#endif
655#ifdef RTDXT_DEBUG_HOST
656 glFinish();
657 TIMER_STOP_PRINT("Texture Compress: ");
658 TIMER_START();
659#endif
660
661
662 glReadBuffer(GL_COLOR_ATTACHMENT0_EXT);
663
664#ifdef USE_PBO_DXT_ENCODER
665 // Read back
666 // read pixels from framebuffer to PBO
667 // glReadPixels() should return immediately.
668 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, encoder->pbo_out);
669 if ( encoder->type == DXT_TYPE_DXT5_YCOCG )
670 glReadPixels(0, 0, (encoder->width + 3) / 4, (encoder->height + 3) / 4, GL_RGBA_INTEGER_EXT, GL_UNSIGNED_INT, 0);
671 else
672 glReadPixels(0, 0, (encoder->width + 3) / 4, (encoder->height + 3) / 4 , GL_RGBA_INTEGER_EXT, GL_UNSIGNED_SHORT, 0);
673
674 // map the PBO to process its data by CPU
675 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, encoder->pbo_out);
676 ptr = (GLubyte*)glMapBufferARB(GL_PIXEL_PACK_BUFFER_ARB,
677 GL_READ_ONLY_ARB);
678 if(ptr)
679 {
680 memcpy(image_compressed, ptr, ((encoder->width + 3) / 4 * 4) * ((encoder->height + 3) / 4 * 4) / (encoder->type == DXT_TYPE_DXT5_YCOCG ? 1 : 2));
681 glUnmapBufferARB(GL_PIXEL_PACK_BUFFER_ARB);
682 }
683
684 // back to conventional pixel operation
685 glBindBufferARB(GL_PIXEL_PACK_BUFFER_ARB, 0);
686#else
687 glReadPixels(0, 0, (encoder->width + 3) / 4, (encoder->height + 3) / 4, GL_RGBA_INTEGER_EXT,
688 encoder->type == DXT_TYPE_DXT5_YCOCG ? GL_UNSIGNED_INT : GL_UNSIGNED_SHORT, image_compressed);
689#endif
690
691
692#ifdef RTDXT_DEBUG_HOST
693 glFinish();
694 TIMER_STOP_PRINT("Texture Save: ");
695#endif
696#ifdef RTDXT_DEBUG
697 glEndQuery(GL_TIME_ELAPSED_EXT);
698 {
699 GLint available = 0;
700 GLuint64 load = 0,
701 convert = 0,
702 compress = 0,
703 store = 0;
704 while (!available) {
705 glGetQueryObjectiv(encoder->queries[3], GL_QUERY_RESULT_AVAILABLE, &available);
706 }
707 glGetQueryObjectui64vEXT(encoder->queries[0], GL_QUERY_RESULT, &load);
708 glGetQueryObjectui64vEXT(encoder->queries[1], GL_QUERY_RESULT, &convert);
709 glGetQueryObjectui64vEXT(encoder->queries[2], GL_QUERY_RESULT, &compress);
710 glGetQueryObjectui64vEXT(encoder->queries[3], GL_QUERY_RESULT, &store);
711 printf("Load: %8lu; YUV444->YUV422: %8lu; compress: %8lu; store: %8lu\n",
712 load, convert, compress, store);
713 }
714#endif
715#ifdef HAVE_GPUPERFAPI
716 GPA_EndSample();
717 GPA_EndPass();
718#endif
719
720 return 0;
721}
722
724int
725dxt_encoder_buffer_free(unsigned char* image_compressed)
726{
727 free(image_compressed);
728 return 0;
729}
730
732int
734{
735#ifdef HAVE_GPUPERFAPI
736 GPA_EndSession();
737 bool readyResult = FALSE;
738 if ( encoder->sessionID != encoder->currentWaitSessionID )
739 {
740 GPA_Status sessionStatus;
741 sessionStatus = GPA_IsSessionReady( &readyResult,
742 encoder->currentWaitSessionID );
743 while ( sessionStatus == GPA_STATUS_ERROR_SESSION_NOT_FOUND )
744 {
745 // skipping a session which got overwritten
746 encoder->currentWaitSessionID++;
747 sessionStatus = GPA_IsSessionReady( &readyResult,
748 encoder->currentWaitSessionID );
749 }
750 }
751 if ( readyResult )
752 {
753 WriteSession( encoder->currentWaitSessionID,
754 "GPUPerfAPI-RTDXT-Results.csv" );
755 encoder->currentWaitSessionID++;
756 }
757
758#endif
759 glDeleteShader(encoder->shader_fragment_compress);
760 glDeleteShader(encoder->shader_vertex_compress);
761 glDeleteProgram(encoder->program_compress);
762 free(encoder);
763 return 0;
764}
765
766#ifdef HAVE_GPUPERFAPI
768static void WriteSession( gpa_uint32 currentWaitSessionID,
769 const char* filename )
770{
771 static bool doneHeadings = FALSE;
772 gpa_uint32 count;
773 GPA_GetEnabledCount( &count );
774 FILE* f;
775 if ( !doneHeadings )
776 {
777 const char* name;
778 f = fopen( filename, "w" );
779 assert( f );
780 fprintf( f, "Identifier, " );
781 for (gpa_uint32 counter = 0 ; counter < count ; counter++ )
782 {
783 gpa_uint32 enabledCounterIndex;
784 GPA_GetEnabledIndex( counter, &enabledCounterIndex );
785 GPA_GetCounterName( enabledCounterIndex, &name );
786 fprintf( f, "%s, ", name );
787 }
788 fprintf( f, "\n" );
789 fclose( f );
790 doneHeadings = TRUE;
791 }
792 f = fopen( filename, "a+" );
793 assert( f );
794 gpa_uint32 sampleCount;
795 GPA_GetSampleCount( currentWaitSessionID, &sampleCount );
796 for (gpa_uint32 sample = 0 ; sample < sampleCount ; sample++ )
797 {
798 fprintf( f, "session: %d; sample: %d, ", currentWaitSessionID,
799 sample );
800 for (gpa_uint32 counter = 0 ; counter < count ; counter++ )
801 {
802 gpa_uint32 enabledCounterIndex;
803 GPA_GetEnabledIndex( counter, &enabledCounterIndex );
804 GPA_Type type;
805 GPA_GetCounterDataType( enabledCounterIndex, &type );
806 if ( type == GPA_TYPE_UINT32 )
807 {
808 gpa_uint32 value;
809 GPA_GetSampleUInt32( currentWaitSessionID,
810 sample, enabledCounterIndex, &value );
811 fprintf( f, "%u,", value );
812 }
813 else if ( type == GPA_TYPE_UINT64 )
814 {
815 gpa_uint64 value;
816 GPA_GetSampleUInt64( currentWaitSessionID,
817 sample, enabledCounterIndex, &value );
818 fprintf( f, "%lu,", value );
819 }
820 else if ( type == GPA_TYPE_FLOAT32 )
821 {
822 gpa_float32 value;
823 GPA_GetSampleFloat32( currentWaitSessionID,
824 sample, enabledCounterIndex, &value );
825 fprintf( f, "%f,", (double) value );
826 }
827 else if ( type == GPA_TYPE_FLOAT64 )
828 {
829 gpa_float64 value;
830 GPA_GetSampleFloat64( currentWaitSessionID,
831 sample, enabledCounterIndex, &value );
832 fprintf( f, "%f,", value );
833 }
834 else
835 {
836 assert(FALSE);
837 }
838 }
839 fprintf( f, "\n" );
840 }
841 fclose( f );
842}
843#endif
844
845/* vim: set expandtab sw=4: */
convert_t convert
#define TRUE
#define FALSE
#define DXT_IMAGE_GL_TYPE
Definition dxt_common.h:72
#define TIMER_STOP_PRINT(text)
Definition dxt_common.h:64
dxt_format
Definition dxt_common.h:78
@ DXT_FORMAT_RGBA
Definition dxt_common.h:80
@ DXT_FORMAT_YUV
Definition dxt_common.h:81
@ DXT_FORMAT_YUV422
Definition dxt_common.h:82
@ DXT_FORMAT_RGB
Definition dxt_common.h:79
#define TIMER_START()
Definition dxt_common.h:56
dxt_type
Definition dxt_common.h:88
@ DXT_TYPE_DXT1_YUV
Definition dxt_common.h:90
@ DXT_TYPE_DXT1
Definition dxt_common.h:89
@ DXT_TYPE_DXT5_YCOCG
Definition dxt_common.h:91
#define TIMER_INIT()
Definition dxt_common.h:52
#define DXT_IMAGE_TYPE
Definition dxt_common.h:71
int dxt_encoder_buffer_allocate(struct dxt_encoder *encoder, unsigned char **image_compressed, int *image_compressed_size)
static GLfloat points[]
Definition dxt_encoder.c:61
const int FORMAT_YUV
Definition dxt_encoder.c:71
const int FORMAT_RGB
Definition dxt_encoder.c:70
int dxt_encoder_compress_texture(struct dxt_encoder *encoder, int texture, unsigned char *image_compressed)
int dxt_encoder_compress(struct dxt_encoder *encoder, DXT_IMAGE_TYPE *image, unsigned char *image_compressed)
struct dxt_encoder * dxt_encoder_create(enum dxt_type type, int width, int height, enum dxt_format format, int legacy)
static int dxt_prepare_yuv422_shader(struct dxt_encoder *encoder)
int dxt_encoder_destroy(struct dxt_encoder *encoder)
int dxt_encoder_buffer_free(unsigned char *image_compressed)
GLuint dxt_shader_create_from_source(const char *source, GLenum type)
Definition dxt_util.c:32
int count
Definition hd-rum.c:44
Option::OptType type
Definition settings.cpp:194
const char * name
Definition settings.cpp:193
GLuint g_vertices
GLuint yuv422_to_444_program
GLuint shader_vertex_compress
enum dxt_format format
Definition dxt_encoder.c:88
GLuint fbo444_id
GLuint yuv422_to_444_vp
GLuint shader_fragment_compress
GLuint texture_yuv422
GLuint fbo_id
enum dxt_type type
Definition dxt_encoder.c:79
GLuint program_compress
GLuint yuv422_to_444_fp
GLuint texture_id
Definition dxt_encoder.c:91
unsigned int legacy
Definition dxt_encoder.c:76
GLuint texture_compressed_id
GLuint g_vao_422