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