Rev 4525 | Rev 4768 | Go to most recent revision | Only display areas with differences | Regard whitespace | Details | Blame | Last modification | View Log | RSS feed
Rev 4525 | Rev 4526 | ||
---|---|---|---|
1 | #include |
1 | #include |
2 | #include |
2 | #include |
3 | #include |
3 | #include |
4 | #include |
4 | #include |
5 | 5 | ||
6 | #include "render.h" |
6 | #include "render.h" |
7 | #include |
7 | #include |
8 | #include |
8 | #include |
9 | 9 | ||
10 | void create_mask(struct render *render); |
10 | void create_mask(struct render *render); |
11 | 11 | ||
12 | static int drm_ioctl(int fd, unsigned long request, void *arg) |
12 | static int drm_ioctl(int fd, unsigned long request, void *arg) |
13 | { |
13 | { |
14 | ioctl_t io; |
14 | ioctl_t io; |
15 | 15 | ||
16 | io.handle = fd; |
16 | io.handle = fd; |
17 | io.io_code = request; |
17 | io.io_code = request; |
18 | io.input = arg; |
18 | io.input = arg; |
19 | io.inp_size = 64; |
19 | io.inp_size = 64; |
20 | io.output = NULL; |
20 | io.output = NULL; |
21 | io.out_size = 0; |
21 | io.out_size = 0; |
22 | 22 | ||
23 | return call_service(&io); |
23 | return call_service(&io); |
24 | } |
24 | } |
25 | 25 | ||
26 | static EGLImageKHR px_create_image(EGLDisplay display, EGLContext context, |
26 | static EGLImageKHR px_create_image(EGLDisplay display, EGLContext context, |
27 | int width, int height, int stride, int name) |
27 | int width, int height, int stride, int name) |
28 | { |
28 | { |
29 | EGLImageKHR image; |
29 | EGLImageKHR image; |
30 | EGLint attribs[] = { |
30 | EGLint attribs[] = { |
31 | EGL_WIDTH, 0, |
31 | EGL_WIDTH, 0, |
32 | EGL_HEIGHT, 0, |
32 | EGL_HEIGHT, 0, |
33 | EGL_DRM_BUFFER_STRIDE_MESA, 0, |
33 | EGL_DRM_BUFFER_STRIDE_MESA, 0, |
34 | EGL_DRM_BUFFER_FORMAT_MESA, |
34 | EGL_DRM_BUFFER_FORMAT_MESA, |
35 | EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, |
35 | EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, |
36 | EGL_DRM_BUFFER_USE_MESA, |
36 | EGL_DRM_BUFFER_USE_MESA, |
37 | EGL_DRM_BUFFER_USE_SHARE_MESA | |
37 | EGL_DRM_BUFFER_USE_SHARE_MESA | |
38 | EGL_DRM_BUFFER_USE_SCANOUT_MESA, |
38 | EGL_DRM_BUFFER_USE_SCANOUT_MESA, |
39 | EGL_NONE |
39 | EGL_NONE |
40 | }; |
40 | }; |
41 | attribs[1] = width; |
41 | attribs[1] = width; |
42 | attribs[3] = height; |
42 | attribs[3] = height; |
43 | attribs[5] = stride/4; |
43 | attribs[5] = stride/4; |
44 | 44 | ||
45 | printf("%s w:%d :%d pitch:%d handle %d\n", __FUNCTION__, |
45 | printf("%s w:%d :%d pitch:%d handle %d\n", __FUNCTION__, |
46 | width, height, stride, name); |
46 | width, height, stride, name); |
47 | 47 | ||
48 | image = eglCreateImageKHR(display, context, EGL_DRM_BUFFER_MESA, |
48 | image = eglCreateImageKHR(display, context, EGL_DRM_BUFFER_MESA, |
49 | (void *) (uintptr_t)name, attribs); |
49 | (void *) (uintptr_t)name, attribs); |
50 | 50 | ||
51 | return image; |
51 | return image; |
52 | } |
52 | } |
53 | 53 | ||
54 | static GLint create_shader(GLenum type, const char *source) |
54 | static GLint create_shader(GLenum type, const char *source) |
55 | { |
55 | { |
56 | GLint ok; |
56 | GLint ok; |
57 | GLint shader; |
57 | GLint shader; |
58 | 58 | ||
59 | shader = glCreateShader(type); |
59 | shader = glCreateShader(type); |
60 | if(shader == 0) |
60 | if(shader == 0) |
61 | goto err; |
61 | goto err; |
62 | 62 | ||
63 | glShaderSource(shader, 1, (const GLchar **) &source, NULL); |
63 | glShaderSource(shader, 1, (const GLchar **) &source, NULL); |
64 | glCompileShader(shader); |
64 | glCompileShader(shader); |
65 | glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); |
65 | glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); |
66 | if (!ok) { |
66 | if (!ok) { |
67 | GLchar *info; |
67 | GLchar *info; |
68 | GLint size; |
68 | GLint size; |
69 | 69 | ||
70 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); |
70 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); |
71 | info = malloc(size); |
71 | info = malloc(size); |
72 | 72 | ||
73 | glGetShaderInfoLog(shader, size, NULL, info); |
73 | glGetShaderInfoLog(shader, size, NULL, info); |
74 | printf("Failed to compile %s: %s\n", |
74 | printf("Failed to compile %s: %s\n", |
75 | type == GL_FRAGMENT_SHADER ? "FS" : "VS",info); |
75 | type == GL_FRAGMENT_SHADER ? "FS" : "VS",info); |
76 | printf("Program source:\n%s", source); |
76 | printf("Program source:\n%s", source); |
77 | printf("GLSL compile failure\n"); |
77 | printf("GLSL compile failure\n"); |
78 | free(info); |
78 | free(info); |
79 | glDeleteProgram(shader); |
79 | glDeleteProgram(shader); |
80 | shader = 0; |
80 | shader = 0; |
81 | } |
81 | } |
82 | err: |
82 | err: |
83 | return shader; |
83 | return shader; |
84 | } |
84 | } |
85 | 85 | ||
86 | 86 | ||
87 | struct render* create_render(EGLDisplay dpy, EGLSurface surface, int dx, int dy) |
87 | struct render* create_render(EGLDisplay dpy, EGLSurface surface, int dx, int dy) |
88 | { |
88 | { |
89 | const char *vs_src = |
89 | const char *vs_src = |
90 | "attribute vec4 v_position;\n" |
90 | "attribute vec4 v_position;\n" |
91 | "attribute vec4 v_texcoord0;\n" |
91 | "attribute vec4 v_texcoord0;\n" |
92 | "varying vec2 source_texture;\n" |
92 | "varying vec2 source_texture;\n" |
93 | "void main()\n" |
93 | "void main()\n" |
94 | "{\n" |
94 | "{\n" |
95 | " gl_Position = v_position;\n" |
95 | " gl_Position = v_position;\n" |
96 | " source_texture = v_texcoord0.xy;\n" |
96 | " source_texture = v_texcoord0.xy;\n" |
97 | "}\n"; |
97 | "}\n"; |
98 | 98 | ||
99 | const char *fs_src = |
99 | const char *fs_src = |
100 | "varying vec2 source_texture;\n" |
100 | "varying vec2 source_texture;\n" |
101 | "uniform sampler2D sampler_src;\n" |
101 | "uniform sampler2D sampler_src;\n" |
102 | "uniform sampler2D sampler_mask;\n" |
102 | "uniform sampler2D sampler_mask;\n" |
103 | "void main()\n" |
103 | "void main()\n" |
104 | "{\n" |
104 | "{\n" |
105 | " float ca = texture2D(sampler_mask, source_texture).r;\n" |
105 | " float ca = texture2D(sampler_mask, source_texture).r;\n" |
106 | " gl_FragColor = vec4(texture2D(sampler_src, source_texture).rgb, ca);\n" |
106 | " gl_FragColor = vec4(texture2D(sampler_src, source_texture).rgb, ca);\n" |
107 | "}\n"; |
107 | "}\n"; |
108 | 108 | ||
109 | EGLint config_attribs[14]; |
109 | EGLint config_attribs[14]; |
110 | EGLConfig config; |
110 | EGLConfig config; |
111 | EGLint num_configs; |
111 | EGLint num_configs; |
112 | 112 | ||
113 | EGLContext context; |
113 | EGLContext context; |
114 | 114 | ||
115 | struct drm_i915_fb_info fb; |
115 | struct drm_i915_fb_info fb; |
116 | GLint vs_shader, fs_shader; |
116 | GLint vs_shader, fs_shader; |
117 | GLenum status; |
117 | GLenum status; |
118 | GLint ret; |
118 | GLint ret; |
119 | int fd; |
119 | int fd; |
120 | struct render *render; |
120 | struct render *render; |
121 | 121 | ||
122 | 122 | ||
123 | fd = get_service("DISPLAY"); |
123 | fd = get_service("DISPLAY"); |
124 | 124 | ||
125 | memset(&fb, 0, sizeof(fb)); |
125 | memset(&fb, 0, sizeof(fb)); |
126 | ret = drm_ioctl(fd, SRV_FBINFO, &fb); |
126 | ret = drm_ioctl(fd, SRV_FBINFO, &fb); |
127 | if( ret != 0 ) |
127 | if( ret != 0 ) |
128 | { printf("failed to get framebuffer info\n"); |
128 | { printf("failed to get framebuffer info\n"); |
129 | goto err; |
129 | goto err; |
130 | }; |
130 | }; |
131 | 131 | ||
132 | render = (struct render*)malloc(sizeof(struct render)); |
132 | render = (struct render*)malloc(sizeof(struct render)); |
133 | if(render == NULL) |
133 | if(render == NULL) |
134 | goto err; |
134 | goto err; |
135 | 135 | ||
136 | render->fd = fd; |
136 | render->fd = fd; |
137 | render->dpy = dpy; |
137 | render->dpy = dpy; |
138 | render->dx = dx; |
138 | render->dx = dx; |
139 | render->dy = dy; |
139 | render->dy = dy; |
140 | 140 | ||
141 | if(!eglQuerySurface(dpy, surface, EGL_WIDTH, &render->width)) |
141 | if(!eglQuerySurface(dpy, surface, EGL_WIDTH, &render->width)) |
142 | goto err1; |
142 | goto err1; |
143 | 143 | ||
144 | if(!eglQuerySurface(dpy, surface, EGL_HEIGHT, &render->height)) |
144 | if(!eglQuerySurface(dpy, surface, EGL_HEIGHT, &render->height)) |
145 | goto err1; |
145 | goto err1; |
146 | 146 | ||
147 | render->scr_width = fb.width; |
147 | render->scr_width = fb.width; |
148 | render->scr_height = fb.height; |
148 | render->scr_height = fb.height; |
149 | 149 | ||
150 | render->front = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_FRONT); |
150 | render->front = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_FRONT); |
151 | if(render->front == EGL_NO_IMAGE_KHR) |
151 | if(render->front == EGL_NO_IMAGE_KHR) |
152 | goto err1; |
152 | goto err1; |
153 | 153 | ||
154 | render->back = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_BACK); |
154 | render->back = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_BACK); |
155 | if( render->back == EGL_NO_IMAGE_KHR) |
155 | if( render->back == EGL_NO_IMAGE_KHR) |
156 | goto err2; |
156 | goto err2; |
157 | 157 | ||
158 | 158 | ||
159 | context = eglGetCurrentContext(); |
159 | context = eglGetCurrentContext(); |
160 | 160 | ||
161 | config_attribs[0] = EGL_RED_SIZE; |
161 | config_attribs[0] = EGL_RED_SIZE; |
162 | config_attribs[1] = 1; |
162 | config_attribs[1] = 1; |
163 | config_attribs[2] = EGL_GREEN_SIZE; |
163 | config_attribs[2] = EGL_GREEN_SIZE; |
164 | config_attribs[3] = 1; |
164 | config_attribs[3] = 1; |
165 | config_attribs[4] = EGL_BLUE_SIZE; |
165 | config_attribs[4] = EGL_BLUE_SIZE; |
166 | config_attribs[5] = 1; |
166 | config_attribs[5] = 1; |
167 | config_attribs[6] = EGL_DEPTH_SIZE; |
167 | config_attribs[6] = EGL_DEPTH_SIZE; |
168 | config_attribs[7] = 1; |
168 | config_attribs[7] = 1; |
169 | 169 | ||
170 | config_attribs[8] = EGL_SURFACE_TYPE; |
170 | config_attribs[8] = EGL_SURFACE_TYPE; |
171 | config_attribs[9] = EGL_WINDOW_BIT; |
171 | config_attribs[9] = EGL_WINDOW_BIT; |
172 | 172 | ||
173 | config_attribs[10] = EGL_RENDERABLE_TYPE; |
173 | config_attribs[10] = EGL_RENDERABLE_TYPE; |
174 | config_attribs[11] = EGL_OPENGL_BIT; |
174 | config_attribs[11] = EGL_OPENGL_BIT; |
175 | config_attribs[12] = EGL_NONE; |
175 | config_attribs[12] = EGL_NONE; |
176 | 176 | ||
177 | if (!eglChooseConfig(dpy,config_attribs, &config, 1, &num_configs) || !num_configs) |
177 | if (!eglChooseConfig(dpy,config_attribs, &config, 1, &num_configs) || !num_configs) |
178 | { |
178 | { |
179 | printf("failed to choose a config"); |
179 | printf("failed to choose a config"); |
180 | goto err3; |
180 | goto err3; |
181 | } |
181 | } |
182 | 182 | ||
183 | render->context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL); |
183 | render->context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL); |
184 | if (!context) |
184 | if (!context) |
185 | { |
185 | { |
186 | printf("failed to create context"); |
186 | printf("failed to create context"); |
187 | goto err3; |
187 | goto err3; |
188 | }; |
188 | }; |
189 | 189 | ||
190 | if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, render->context)) |
190 | if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, render->context)) |
191 | { |
191 | { |
192 | printf("failed to make window current"); |
192 | printf("failed to make window current"); |
193 | goto err4; |
193 | goto err4; |
194 | }; |
194 | }; |
195 | 195 | ||
196 | 196 | ||
197 | glGenTextures(2, render->tx_buffers); |
197 | glGenTextures(2, render->tx_buffers); |
198 | if(glGetError() != GL_NO_ERROR) |
198 | if(glGetError() != GL_NO_ERROR) |
199 | goto err5; |
199 | goto err5; |
200 | 200 | ||
201 | glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_FRONT]); |
201 | glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_FRONT]); |
202 | if(glGetError() != GL_NO_ERROR) |
202 | if(glGetError() != GL_NO_ERROR) |
203 | goto err6; |
203 | goto err6; |
204 | 204 | ||
205 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
205 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
206 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
206 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
207 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->front); |
207 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->front); |
208 | if(glGetError() != GL_NO_ERROR) |
208 | if(glGetError() != GL_NO_ERROR) |
209 | goto err6; |
209 | goto err6; |
210 | 210 | ||
211 | glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_BACK]); |
211 | glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_BACK]); |
212 | if(glGetError() != GL_NO_ERROR) |
212 | if(glGetError() != GL_NO_ERROR) |
213 | goto err6; |
213 | goto err6; |
214 | 214 | ||
215 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
215 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
216 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
216 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
217 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->back); |
217 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->back); |
218 | if(glGetError() != GL_NO_ERROR) |
218 | if(glGetError() != GL_NO_ERROR) |
219 | goto err6; |
219 | goto err6; |
220 | 220 | ||
221 | glBindTexture(GL_TEXTURE_2D, 0); |
221 | glBindTexture(GL_TEXTURE_2D, 0); |
222 | 222 | ||
223 | render->back_buffer = EGL_DRM_BUFFER_FRONT; |
223 | render->back_buffer = EGL_DRM_BUFFER_FRONT; |
224 | 224 | ||
225 | render->screen = px_create_image(dpy,context,fb.width,fb.height, |
225 | render->screen = px_create_image(dpy,context,fb.width,fb.height, |
226 | fb.pitch,fb.name); |
226 | fb.pitch,fb.name); |
227 | if(render->screen == EGL_NO_IMAGE_KHR) |
227 | if(render->screen == EGL_NO_IMAGE_KHR) |
228 | goto err6; |
228 | goto err6; |
229 | 229 | ||
230 | glGenTextures(1, &render->tx_screen); |
230 | glGenTextures(1, &render->tx_screen); |
231 | if(glGetError() != GL_NO_ERROR) |
231 | if(glGetError() != GL_NO_ERROR) |
232 | goto err6; |
232 | goto err6; |
233 | 233 | ||
234 | glBindTexture(GL_TEXTURE_2D, render->tx_screen); |
234 | glBindTexture(GL_TEXTURE_2D, render->tx_screen); |
235 | if(glGetError() != GL_NO_ERROR) |
235 | if(glGetError() != GL_NO_ERROR) |
236 | goto err7; |
236 | goto err7; |
237 | 237 | ||
238 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
238 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
239 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
239 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
240 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->screen); |
240 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->screen); |
241 | if(glGetError() != GL_NO_ERROR) |
241 | if(glGetError() != GL_NO_ERROR) |
242 | goto err7; |
242 | goto err7; |
243 | 243 | ||
244 | glBindTexture(GL_TEXTURE_2D, 0); |
244 | glBindTexture(GL_TEXTURE_2D, 0); |
245 | 245 | ||
246 | create_mask(render); |
246 | create_mask(render); |
247 | 247 | ||
248 | glGenFramebuffers(1, &render->framebuffer); |
248 | glGenFramebuffers(1, &render->framebuffer); |
249 | if(glGetError() != GL_NO_ERROR) |
249 | if(glGetError() != GL_NO_ERROR) |
250 | goto err8; |
250 | goto err8; |
251 | 251 | ||
252 | glBindFramebuffer(GL_FRAMEBUFFER, render->framebuffer); |
252 | glBindFramebuffer(GL_FRAMEBUFFER, render->framebuffer); |
253 | if(glGetError() != GL_NO_ERROR) |
253 | if(glGetError() != GL_NO_ERROR) |
254 | goto err9; |
254 | goto err9; |
255 | 255 | ||
256 | glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, |
256 | glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, |
257 | GL_TEXTURE_2D, render->tx_screen,0); |
257 | GL_TEXTURE_2D, render->tx_screen,0); |
258 | 258 | ||
259 | status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
259 | status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
260 | if (status != GL_FRAMEBUFFER_COMPLETE) |
260 | if (status != GL_FRAMEBUFFER_COMPLETE) |
261 | { |
261 | { |
262 | const char *str; |
262 | const char *str; |
263 | switch (status) |
263 | switch (status) |
264 | { |
264 | { |
265 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: |
265 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: |
266 | str = "incomplete attachment"; |
266 | str = "incomplete attachment"; |
267 | break; |
267 | break; |
268 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: |
268 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: |
269 | str = "incomplete/missing attachment"; |
269 | str = "incomplete/missing attachment"; |
270 | break; |
270 | break; |
271 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: |
271 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: |
272 | str = "incomplete draw buffer"; |
272 | str = "incomplete draw buffer"; |
273 | break; |
273 | break; |
274 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: |
274 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: |
275 | str = "incomplete read buffer"; |
275 | str = "incomplete read buffer"; |
276 | break; |
276 | break; |
277 | case GL_FRAMEBUFFER_UNSUPPORTED: |
277 | case GL_FRAMEBUFFER_UNSUPPORTED: |
278 | str = "unsupported"; |
278 | str = "unsupported"; |
279 | break; |
279 | break; |
280 | case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: |
280 | case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: |
281 | str = "incomplete multiple"; |
281 | str = "incomplete multiple"; |
282 | break; |
282 | break; |
283 | default: |
283 | default: |
284 | str = "unknown error"; |
284 | str = "unknown error"; |
285 | break; |
285 | break; |
286 | } |
286 | } |
287 | printf("destination is framebuffer incomplete: %s [%#x]\n", str, status); |
287 | printf("destination is framebuffer incomplete: %s [%#x]\n", str, status); |
288 | goto err9; |
288 | goto err9; |
289 | } |
289 | } |
290 | 290 | ||
291 | glViewport(0, 0, render->scr_width, render->scr_height); |
291 | glViewport(0, 0, render->scr_width, render->scr_height); |
292 | glMatrixMode(GL_PROJECTION); |
292 | glMatrixMode(GL_PROJECTION); |
293 | glLoadIdentity(); |
293 | glLoadIdentity(); |
294 | glMatrixMode(GL_MODELVIEW); |
294 | glMatrixMode(GL_MODELVIEW); |
295 | glLoadIdentity(); |
295 | glLoadIdentity(); |
296 | 296 | ||
297 | render->blit_prog = glCreateProgram(); |
297 | render->blit_prog = glCreateProgram(); |
298 | if(render->blit_prog == 0) |
298 | if(render->blit_prog == 0) |
299 | goto err9; |
299 | goto err9; |
300 | 300 | ||
301 | vs_shader = create_shader(GL_VERTEX_SHADER,vs_src); |
301 | vs_shader = create_shader(GL_VERTEX_SHADER,vs_src); |
302 | if(vs_shader == 0) |
302 | if(vs_shader == 0) |
303 | goto err10; |
303 | goto err10; |
304 | 304 | ||
305 | fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_src); |
305 | fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_src); |
306 | if(fs_shader == 0) |
306 | if(fs_shader == 0) |
307 | goto err11; |
307 | goto err11; |
308 | 308 | ||
309 | glAttachShader(render->blit_prog, vs_shader); |
309 | glAttachShader(render->blit_prog, vs_shader); |
310 | glAttachShader(render->blit_prog, fs_shader); |
310 | glAttachShader(render->blit_prog, fs_shader); |
311 | glBindAttribLocation(render->blit_prog, 0, "v_position"); |
311 | glBindAttribLocation(render->blit_prog, 0, "v_position"); |
312 | glBindAttribLocation(render->blit_prog, 1, "v_texcoord0"); |
312 | glBindAttribLocation(render->blit_prog, 1, "v_texcoord0"); |
313 | 313 | ||
314 | glLinkProgram(render->blit_prog); |
314 | glLinkProgram(render->blit_prog); |
315 | glGetProgramiv(render->blit_prog, GL_LINK_STATUS, &ret); |
315 | glGetProgramiv(render->blit_prog, GL_LINK_STATUS, &ret); |
316 | if (!ret) |
316 | if (!ret) |
317 | { |
317 | { |
318 | GLchar *info; |
318 | GLchar *info; |
319 | GLint size; |
319 | GLint size; |
320 | 320 | ||
321 | glGetProgramiv(render->blit_prog, GL_INFO_LOG_LENGTH, &size); |
321 | glGetProgramiv(render->blit_prog, GL_INFO_LOG_LENGTH, &size); |
322 | info = malloc(size); |
322 | info = malloc(size); |
323 | 323 | ||
324 | glGetProgramInfoLog(render->blit_prog, size, NULL, info); |
324 | glGetProgramInfoLog(render->blit_prog, size, NULL, info); |
325 | printf("Failed to link: %s\n", info); |
325 | printf("Failed to link: %s\n", info); |
326 | printf("GLSL link failure\n"); |
326 | printf("GLSL link failure\n"); |
327 | free(info); |
327 | free(info); |
328 | } |
328 | } |
329 | 329 | ||
330 | render->sampler = glGetUniformLocation(render->blit_prog,"sampler_src"); |
330 | render->sampler = glGetUniformLocation(render->blit_prog,"sampler_src"); |
331 | render->sm_mask = glGetUniformLocation(render->blit_prog,"sampler_mask"); |
331 | render->sm_mask = glGetUniformLocation(render->blit_prog,"sampler_mask"); |
332 | 332 | ||
333 | glUseProgram(render->blit_prog); |
333 | glUseProgram(render->blit_prog); |
334 | glUniform1i(render->sampler, 0); |
334 | glUniform1i(render->sampler, 0); |
335 | glUniform1i(render->sm_mask, 1); |
335 | glUniform1i(render->sm_mask, 1); |
336 | 336 | ||
337 | glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),render->vertices); |
337 | glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),render->vertices); |
338 | glEnableVertexAttribArray(0); |
338 | glEnableVertexAttribArray(0); |
339 | 339 | ||
340 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),render->tc_src); |
340 | glVertexAttribPointer(1, 2, GL_FLOAT, GL_FALSE, 2 * sizeof(float),render->tc_src); |
341 | glEnableVertexAttribArray(1); |
341 | glEnableVertexAttribArray(1); |
- | 342 | ||
- | 343 | render->tc_src[0] = 0.0; |
|
- | 344 | render->tc_src[1] = 0.0; |
|
- | 345 | render->tc_src[1*2] = 1.0; |
|
- | 346 | render->tc_src[1*2+1]= 0.0; |
|
- | 347 | render->tc_src[2*2] = 1.0; |
|
- | 348 | render->tc_src[2*2+1]= 1.0; |
|
- | 349 | render->tc_src[3*2] = 0.0; |
|
- | 350 | render->tc_src[3*2+1]= 1.0; |
|
342 | 351 | ||
343 | glEnable(GL_BLEND); |
352 | glEnable(GL_BLEND); |
344 | glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); |
353 | glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); |
345 | 354 | ||
346 | glActiveTexture(GL_TEXTURE1); |
355 | glActiveTexture(GL_TEXTURE1); |
347 | glBindTexture(GL_TEXTURE_2D, render->tx_mask); |
356 | glBindTexture(GL_TEXTURE_2D, render->tx_mask); |
348 | glTexParameteri(GL_TEXTURE_2D, |
357 | glTexParameteri(GL_TEXTURE_2D, |
349 | GL_TEXTURE_MIN_FILTER, |
358 | GL_TEXTURE_MIN_FILTER, |
350 | GL_NEAREST); |
359 | GL_NEAREST); |
351 | glTexParameteri(GL_TEXTURE_2D, |
360 | glTexParameteri(GL_TEXTURE_2D, |
352 | GL_TEXTURE_MAG_FILTER, |
361 | GL_TEXTURE_MAG_FILTER, |
353 | GL_NEAREST); |
362 | GL_NEAREST); |
354 | 363 | ||
355 | eglMakeCurrent(dpy, surface, surface, context); |
364 | eglMakeCurrent(dpy, surface, surface, context); |
356 | 365 | ||
357 | return render; |
366 | return render; |
358 | 367 | ||
359 | err11: |
368 | err11: |
360 | glDeleteShader(vs_shader); |
369 | glDeleteShader(vs_shader); |
361 | err10: |
370 | err10: |
362 | glDeleteProgram(render->blit_prog); |
371 | glDeleteProgram(render->blit_prog); |
363 | err9: |
372 | err9: |
364 | glDeleteFramebuffers(1, &render->framebuffer); |
373 | glDeleteFramebuffers(1, &render->framebuffer); |
365 | err8: |
374 | err8: |
366 | eglDestroyImageKHR(dpy, render->screen); |
375 | eglDestroyImageKHR(dpy, render->screen); |
367 | err7: |
376 | err7: |
368 | glDeleteTextures(1, &render->tx_screen); |
377 | glDeleteTextures(1, &render->tx_screen); |
369 | err6: |
378 | err6: |
370 | glDeleteTextures(2, render->tx_buffers); |
379 | glDeleteTextures(2, render->tx_buffers); |
371 | err5: |
380 | err5: |
372 | eglMakeCurrent(dpy, surface, surface, context); |
381 | eglMakeCurrent(dpy, surface, surface, context); |
373 | err4: |
382 | err4: |
374 | eglDestroyContext(dpy, render->context); |
383 | eglDestroyContext(dpy, render->context); |
375 | err3: |
384 | err3: |
376 | eglDestroyImageKHR(dpy, render->back); |
385 | eglDestroyImageKHR(dpy, render->back); |
377 | err2: |
386 | err2: |
378 | eglDestroyImageKHR(dpy, render->front); |
387 | eglDestroyImageKHR(dpy, render->front); |
379 | err1: |
388 | err1: |
380 | free(render); |
389 | free(render); |
381 | err: |
390 | err: |
382 | return NULL; |
391 | return NULL; |
383 | }; |
392 | }; |
384 | 393 | ||
385 | 394 | ||
386 | 395 | ||
387 | 396 | ||
388 | void create_mask(struct render *render) |
397 | void create_mask(struct render *render) |
389 | { |
398 | { |
390 | struct drm_i915_gem_create create; |
399 | struct drm_i915_gem_create create; |
391 | struct drm_gem_flink flink; |
400 | struct drm_gem_flink flink; |
392 | 401 | ||
393 | struct drm_i915_gem_mmap mmap_arg; |
402 | struct drm_i915_gem_mmap mmap_arg; |
394 | EGLint handle, stride; |
403 | EGLint handle, stride; |
395 | int winw, winh, pitch; |
404 | int winw, winh, pitch; |
396 | void *data; |
405 | void *data; |
397 | int ret; |
406 | int ret; |
398 | GLuint mask_handle, mask_name; |
407 | GLuint mask_handle, mask_name; |
399 | EGLImageKHR mask_image; |
408 | EGLImageKHR mask_image; |
400 | 409 | ||
401 | 410 | ||
402 | glGenTextures(1, &render->tx_mask); |
411 | glGenTextures(1, &render->tx_mask); |
403 | if(glGetError() != GL_NO_ERROR) |
412 | if(glGetError() != GL_NO_ERROR) |
404 | return; |
413 | return; |
405 | 414 | ||
406 | glBindTexture(GL_TEXTURE_2D, render->tx_mask); |
415 | glBindTexture(GL_TEXTURE_2D, render->tx_mask); |
407 | if(glGetError() != GL_NO_ERROR) |
416 | if(glGetError() != GL_NO_ERROR) |
408 | goto err1; |
417 | goto err1; |
409 | 418 | ||
410 | 419 | ||
411 | pitch = (render->width+15) & ~15; |
420 | pitch = (render->width+15) & ~15; |
412 | 421 | ||
413 | create.size = pitch *render->height; |
422 | create.size = pitch *render->height; |
414 | create.handle = 0; |
423 | create.handle = 0; |
415 | ret = drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_CREATE, &create); |
424 | ret = drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_CREATE, &create); |
416 | if(ret != 0) |
425 | if(ret != 0) |
417 | goto err1; |
426 | goto err1; |
418 | 427 | ||
419 | flink.handle = create.handle; |
428 | flink.handle = create.handle; |
420 | ret = drm_ioctl(render->fd, DRM_IOCTL_GEM_FLINK, &flink); |
429 | ret = drm_ioctl(render->fd, DRM_IOCTL_GEM_FLINK, &flink); |
421 | if (ret != 0) |
430 | if (ret != 0) |
422 | goto err2; |
431 | goto err2; |
423 | 432 | ||
424 | mask_handle = create.handle; |
433 | mask_handle = create.handle; |
425 | mask_name = flink.name; |
434 | mask_name = flink.name; |
426 | 435 | ||
427 | printf("create mask bo handle %d name %d\n", create.handle, flink.name); |
436 | printf("create mask bo handle %d name %d\n", create.handle, flink.name); |
428 | 437 | ||
429 | EGLint attribs[] = { |
438 | EGLint attribs[] = { |
430 | EGL_WIDTH, 0, |
439 | EGL_WIDTH, 0, |
431 | EGL_HEIGHT, 0, |
440 | EGL_HEIGHT, 0, |
432 | EGL_DRM_BUFFER_STRIDE_MESA, 0, |
441 | EGL_DRM_BUFFER_STRIDE_MESA, 0, |
433 | EGL_DRM_BUFFER_FORMAT_MESA, |
442 | EGL_DRM_BUFFER_FORMAT_MESA, |
434 | EGL_DRM_BUFFER_FORMAT_R8_MESA, |
443 | EGL_DRM_BUFFER_FORMAT_R8_MESA, |
435 | EGL_DRM_BUFFER_USE_MESA, |
444 | EGL_DRM_BUFFER_USE_MESA, |
436 | EGL_DRM_BUFFER_USE_SHARE_MESA, |
445 | EGL_DRM_BUFFER_USE_SHARE_MESA, |
437 | EGL_NONE |
446 | EGL_NONE |
438 | }; |
447 | }; |
439 | attribs[1] = pitch; |
448 | attribs[1] = pitch; |
440 | attribs[3] = render->height; |
449 | attribs[3] = render->height; |
441 | attribs[5] = pitch; |
450 | attribs[5] = pitch; |
442 | 451 | ||
443 | mask_image = eglCreateImageKHR(render->dpy, render->context, EGL_DRM_BUFFER_MESA, |
452 | mask_image = eglCreateImageKHR(render->dpy, render->context, EGL_DRM_BUFFER_MESA, |
444 | (void *) (uintptr_t)mask_name, attribs); |
453 | (void *) (uintptr_t)mask_name, attribs); |
445 | 454 | ||
446 | printf("create mask image %p\n", mask_image); |
455 | printf("create mask image %p\n", mask_image); |
447 | 456 | ||
448 | 457 | ||
449 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
458 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
450 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
459 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
451 | 460 | ||
452 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mask_image); |
461 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, mask_image); |
453 | 462 | ||
454 | if(glGetError() != GL_NO_ERROR) |
463 | if(glGetError() != GL_NO_ERROR) |
455 | goto err2; |
464 | goto err2; |
456 | 465 | ||
457 | glBindTexture(GL_TEXTURE_2D, 0); |
466 | glBindTexture(GL_TEXTURE_2D, 0); |
458 | 467 | ||
459 | mmap_arg.handle = mask_handle; |
468 | mmap_arg.handle = mask_handle; |
460 | mmap_arg.offset = 0; |
469 | mmap_arg.offset = 0; |
461 | mmap_arg.size = pitch * render->height; |
470 | mmap_arg.size = pitch * render->height; |
462 | if (drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg)) |
471 | if (drm_ioctl(render->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg)) |
463 | { |
472 | { |
464 | printf("%s: failed to mmap image %p handle=%d, %d bytes, into CPU domain\n", |
473 | printf("%s: failed to mmap image %p handle=%d, %d bytes, into CPU domain\n", |
465 | __FUNCTION__, mask_image, mask_handle, pitch * render->height); |
474 | __FUNCTION__, mask_image, mask_handle, pitch * render->height); |
466 | goto err3; |
475 | goto err3; |
467 | } |
476 | } |
468 | 477 | ||
469 | render->mask_handle = mask_handle; |
478 | render->mask_handle = mask_handle; |
470 | render->mask_name = mask_name; |
479 | render->mask_name = mask_name; |
471 | render->mask_buffer = (void *)(uintptr_t)mmap_arg.addr_ptr; |
480 | render->mask_buffer = (void *)(uintptr_t)mmap_arg.addr_ptr; |
472 | render->mask_image = mask_image; |
481 | render->mask_image = mask_image; |
473 | 482 | ||
474 | return; |
483 | return; |
475 | 484 | ||
476 | err3: |
485 | err3: |
477 | // eglDestroyImageKHR(render->dpy, render->mask); |
486 | // eglDestroyImageKHR(render->dpy, render->mask); |
478 | err2: |
487 | err2: |
479 | glBindTexture(GL_TEXTURE_2D, 0); |
488 | glBindTexture(GL_TEXTURE_2D, 0); |
480 | err1: |
489 | err1: |
481 | glDeleteTextures(1, &render->tx_mask); |
490 | glDeleteTextures(1, &render->tx_mask); |
482 | }; |
491 | }; |