1 #include "graphics.hpp"
2 
3 #include "asserts.hpp"
4 #include "preferences.hpp"
5 #include "texture.hpp"
6 #include "texture_frame_buffer.hpp"
7 
8 #if defined(TARGET_OS_HARMATTAN) || defined(TARGET_PANDORA) || defined(TARGET_TEGRA) || defined(TARGET_BLACKBERRY)
9 #include <EGL/egl.h>
10 #define glGenFramebuffersOES        preferences::glGenFramebuffersOES
11 #define glBindFramebufferOES        preferences::glBindFramebufferOES
12 #define glFramebufferTexture2DOES   preferences::glFramebufferTexture2DOES
13 #define glCheckFramebufferStatusOES preferences::glCheckFramebufferStatusOES
14 #endif
15 
16 //define macros that make it easy to make the OpenGL calls in this file.
17 #if defined(USE_GLES2)
18 #define EXT_CALL(call) call
19 #define EXT_MACRO(macro) macro
20 #elif defined(TARGET_OS_HARMATTAN) || defined(TARGET_OS_IPHONE) || defined(TARGET_PANDORA) || defined(TARGET_TEGRA) || defined(TARGET_BLACKBERRY) || defined(__ANDROID__)
21 #define EXT_CALL(call) call##OES
22 #define EXT_MACRO(macro) macro##_OES
23 #elif defined(__APPLE__)
24 #define EXT_CALL(call) call##EXT
25 #define EXT_MACRO(macro) macro##_EXT
26 #else
27 #define EXT_CALL(call) call##EXT
28 #define EXT_MACRO(macro) macro##_EXT
29 #endif
30 
31 namespace texture_frame_buffer {
32 
33 namespace {
34 bool supported = true;
35 GLuint texture_id = 0, texture_id_back = 0;  //ID of the texture which the frame buffer is stored in
36 GLuint framebuffer_id = 0, framebuffer_id_back = 0; //framebuffer object
37 GLint video_framebuffer_id = 0; //the original frame buffer object
38 int frame_buffer_texture_width = 128;
39 int frame_buffer_texture_height = 128;
40 
init_internal(int buffer_width,int buffer_height)41 void init_internal(int buffer_width, int buffer_height)
42 {
43 	// Clear any old errors.
44 	glGetError();
45 	frame_buffer_texture_width = buffer_width;
46 	frame_buffer_texture_height = buffer_height;
47 
48 #if /*defined(__ANDROID__) ||*/ defined(__native_client__)
49 	{
50 		supported = false;
51 		LOG("FRAME BUFFER OBJECT NOT SUPPORTED");
52 		return;
53 	}
54 #endif
55 
56 #if defined(TARGET_OS_HARMATTAN) || defined(TARGET_PANDORA) || defined(TARGET_TEGRA) || defined(TARGET_BLACKBERRY)
57 	if (glGenFramebuffersOES        != NULL &&
58 		glBindFramebufferOES        != NULL &&
59 		glFramebufferTexture2DOES   != NULL &&
60 		glCheckFramebufferStatusOES != NULL)
61 	{
62 		supported = true;
63 	}
64 	else
65 	{
66 		fprintf(stderr, "FRAME BUFFER OBJECT NOT SUPPORTED\n");
67 		supported = false;
68 		return;
69 	}
70 #endif
71 #if defined(__GLEW_H__)
72 	if(!GLEW_EXT_framebuffer_object)
73     {
74 		fprintf(stderr, "FRAME BUFFER OBJECT NOT SUPPORTED\n");
75 		supported = false;
76 		return;
77 	}
78 #endif
79 	fprintf(stderr, "FRAME BUFFER OBJECT IS SUPPORTED\n");
80 
81 #ifndef TARGET_TEGRA
82 	glGetIntegerv(EXT_MACRO(GL_FRAMEBUFFER_BINDING), &video_framebuffer_id);
83 #endif
84 
85 	// Clear any current errors.
86 	GLenum err = glGetError();
87 
88 	glGenTextures(1, &texture_id);
89 	glBindTexture(GL_TEXTURE_2D, texture_id);
90 	glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width(), height(), 0,
91              GL_RGBA, GL_UNSIGNED_BYTE, 0);
92 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
93 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
94 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
95 	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
96 	glBindTexture(GL_TEXTURE_2D, 0);
97 
98 
99 	// create a framebuffer object
100 	EXT_CALL(glGenFramebuffers)(1, &framebuffer_id);
101 	EXT_CALL(glBindFramebuffer)(EXT_MACRO(GL_FRAMEBUFFER), framebuffer_id);
102 
103 	// attach the texture to FBO color attachment point
104 	EXT_CALL(glFramebufferTexture2D)(EXT_MACRO(GL_FRAMEBUFFER), EXT_MACRO(GL_COLOR_ATTACHMENT0),
105                           GL_TEXTURE_2D, texture_id, 0);
106 
107 	// check FBO status
108 	GLenum status = EXT_CALL(glCheckFramebufferStatus)(EXT_MACRO(GL_FRAMEBUFFER));
109 	if(status == EXT_MACRO(GL_FRAMEBUFFER_UNSUPPORTED)) {
110 		std::cerr << "FRAME BUFFER OBJECT NOT SUPPORTED\n";
111 		supported = false;
112 		err = glGetError();
113 	} else {
114 		ASSERT_EQ(status, EXT_MACRO(GL_FRAMEBUFFER_COMPLETE));
115 	}
116 
117 	// switch back to window-system-provided framebuffer
118 	EXT_CALL(glBindFramebuffer)(EXT_MACRO(GL_FRAMEBUFFER), video_framebuffer_id);
119 
120 	err = glGetError();
121 	ASSERT_EQ(err, GL_NO_ERROR);
122 }
123 }
124 
init(int buffer_width,int buffer_height)125 void init(int buffer_width, int buffer_height)
126 {
127 	init_internal(buffer_width, buffer_height);
128 	switch_texture();
129 	init_internal(buffer_width, buffer_height);
130 }
131 
switch_texture()132 void switch_texture()
133 {
134 	std::swap(texture_id, texture_id_back);
135 	std::swap(framebuffer_id, framebuffer_id_back);
136 }
137 
width()138 int width() { return frame_buffer_texture_width; }
height()139 int height() { return frame_buffer_texture_height; }
140 
unsupported()141 bool unsupported()
142 {
143 	return !supported;
144 }
145 
set_render_to_texture()146 void set_render_to_texture()
147 {
148 	EXT_CALL(glBindFramebuffer)(EXT_MACRO(GL_FRAMEBUFFER), framebuffer_id);
149 	glViewport(0, 0, width(), height());
150 }
151 
set_render_to_screen()152 void set_render_to_screen()
153 {
154 	EXT_CALL(glBindFramebuffer)(EXT_MACRO(GL_FRAMEBUFFER), video_framebuffer_id);
155 	glViewport(0, 0, preferences::actual_screen_width(), preferences::actual_screen_height());
156 }
157 
render_scope()158 render_scope::render_scope()
159 {
160 	set_render_to_texture();
161 }
162 
~render_scope()163 render_scope::~render_scope()
164 {
165 	set_render_to_screen();
166 }
167 
set_as_current_texture()168 void set_as_current_texture()
169 {
170 	graphics::texture::set_current_texture(texture_id);
171 }
172 
173 } // namespace texture_frame_buffer
174