Rev 4517 | Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4502 | Serge | 1 | #include |
2 | #include |
||
3 | #include |
||
4 | #include |
||
5 | |||
6 | #include "render.h" |
||
7 | #include |
||
8 | #include |
||
9 | |||
10 | |||
11 | static int drm_ioctl(int fd, unsigned long request, void *arg) |
||
12 | { |
||
13 | ioctl_t io; |
||
14 | |||
15 | io.handle = fd; |
||
16 | io.io_code = request; |
||
17 | io.input = arg; |
||
18 | io.inp_size = 64; |
||
19 | io.output = NULL; |
||
20 | io.out_size = 0; |
||
21 | |||
22 | return call_service(&io); |
||
23 | } |
||
24 | |||
25 | static EGLImageKHR px_create_image(EGLDisplay display, EGLContext context, |
||
26 | int width, int height, int stride, int name) |
||
27 | { |
||
28 | EGLImageKHR image; |
||
29 | EGLint attribs[] = { |
||
30 | EGL_WIDTH, 0, |
||
31 | EGL_HEIGHT, 0, |
||
32 | EGL_DRM_BUFFER_STRIDE_MESA, 0, |
||
33 | EGL_DRM_BUFFER_FORMAT_MESA, |
||
34 | EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, |
||
35 | EGL_DRM_BUFFER_USE_MESA, |
||
36 | EGL_DRM_BUFFER_USE_SHARE_MESA | |
||
37 | EGL_DRM_BUFFER_USE_SCANOUT_MESA, |
||
38 | EGL_NONE |
||
39 | }; |
||
40 | attribs[1] = width; |
||
41 | attribs[3] = height; |
||
42 | attribs[5] = stride/4; |
||
43 | |||
44 | printf("%s w:%d :%d pitch:%d handle %d\n", __FUNCTION__, |
||
45 | width, height, stride, name); |
||
46 | |||
47 | image = eglCreateImageKHR(display, context, EGL_DRM_BUFFER_MESA, |
||
48 | (void *) (uintptr_t)name, attribs); |
||
49 | |||
50 | return image; |
||
51 | } |
||
52 | |||
53 | static GLint create_shader(GLenum type, const char *source) |
||
54 | { |
||
55 | GLint ok; |
||
56 | GLint shader; |
||
57 | |||
58 | shader = glCreateShader(type); |
||
59 | if(shader == 0) |
||
60 | goto err; |
||
61 | |||
62 | glShaderSource(shader, 1, (const GLchar **) &source, NULL); |
||
63 | glCompileShader(shader); |
||
64 | glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); |
||
65 | if (!ok) { |
||
66 | GLchar *info; |
||
67 | GLint size; |
||
68 | |||
69 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); |
||
70 | info = malloc(size); |
||
71 | |||
72 | glGetShaderInfoLog(shader, size, NULL, info); |
||
73 | printf("Failed to compile %s: %s\n", |
||
74 | type == GL_FRAGMENT_SHADER ? "FS" : "VS",info); |
||
75 | printf("Program source:\n%s", source); |
||
76 | printf("GLSL compile failure\n"); |
||
77 | free(info); |
||
78 | glDeleteProgram(shader); |
||
79 | shader = 0; |
||
80 | } |
||
81 | err: |
||
82 | return shader; |
||
83 | } |
||
84 | |||
85 | |||
86 | struct render* create_render(EGLDisplay dpy, EGLSurface surface, int dx, int dy) |
||
87 | { |
||
88 | const char *vs_src = |
||
89 | "attribute vec4 v_position;\n" |
||
90 | "attribute vec4 v_texcoord0;\n" |
||
91 | "varying vec2 source_texture;\n" |
||
92 | "void main()\n" |
||
93 | "{\n" |
||
94 | " gl_Position = v_position;\n" |
||
95 | " source_texture = v_texcoord0.xy;\n" |
||
96 | "}\n"; |
||
97 | |||
98 | const char *fs_src = |
||
99 | // "precision mediump float;\n" |
||
100 | "varying vec2 source_texture;\n" |
||
101 | "uniform sampler2D sampler;\n" |
||
102 | "void main()\n" |
||
103 | "{\n" |
||
104 | " vec3 cg = texture2D(sampler, source_texture).rgb;\n" |
||
105 | " gl_FragColor = vec4(cg.r,cg.g,cg.b,1.0);\n" |
||
106 | "}\n"; |
||
107 | EGLint config_attribs[14]; |
||
108 | EGLConfig config; |
||
109 | EGLint num_configs; |
||
110 | |||
111 | EGLContext context; |
||
112 | |||
113 | struct drm_i915_fb_info fb; |
||
114 | GLint vs_shader, fs_shader; |
||
115 | GLenum status; |
||
116 | GLint ret; |
||
117 | int fd; |
||
118 | struct render *render; |
||
119 | |||
120 | |||
121 | fd = get_service("DISPLAY"); |
||
122 | |||
123 | memset(&fb, 0, sizeof(fb)); |
||
124 | ret = drm_ioctl(fd, SRV_FBINFO, &fb); |
||
125 | if( ret != 0 ) |
||
126 | { printf("failed to get framebuffer info\n"); |
||
127 | goto err; |
||
128 | }; |
||
129 | |||
130 | render = (struct render*)malloc(sizeof(struct render)); |
||
131 | if(render == NULL) |
||
132 | goto err; |
||
133 | |||
134 | render->fd = fd; |
||
135 | render->dpy = dpy; |
||
136 | render->dx = dx; |
||
137 | render->dy = dy; |
||
138 | |||
139 | if(!eglQuerySurface(dpy, surface, EGL_WIDTH, &render->width)) |
||
140 | goto err1; |
||
141 | |||
142 | if(!eglQuerySurface(dpy, surface, EGL_HEIGHT, &render->height)) |
||
143 | goto err1; |
||
144 | |||
145 | render->scr_width = fb.width; |
||
146 | render->scr_height = fb.height; |
||
147 | |||
148 | render->front = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_FRONT); |
||
149 | if(render->front == EGL_NO_IMAGE_KHR) |
||
150 | goto err1; |
||
151 | |||
152 | render->back = eglGetBufferImage(dpy, surface, EGL_DRM_BUFFER_BACK); |
||
153 | if( render->back == EGL_NO_IMAGE_KHR) |
||
154 | goto err2; |
||
155 | |||
156 | |||
157 | context = eglGetCurrentContext(); |
||
158 | |||
159 | config_attribs[0] = EGL_RED_SIZE; |
||
160 | config_attribs[1] = 1; |
||
161 | config_attribs[2] = EGL_GREEN_SIZE; |
||
162 | config_attribs[3] = 1; |
||
163 | config_attribs[4] = EGL_BLUE_SIZE; |
||
164 | config_attribs[5] = 1; |
||
165 | config_attribs[6] = EGL_DEPTH_SIZE; |
||
166 | config_attribs[7] = 1; |
||
167 | |||
168 | config_attribs[8] = EGL_SURFACE_TYPE; |
||
169 | config_attribs[9] = EGL_WINDOW_BIT; |
||
170 | |||
171 | config_attribs[10] = EGL_RENDERABLE_TYPE; |
||
172 | config_attribs[11] = EGL_OPENGL_BIT; |
||
173 | config_attribs[12] = EGL_NONE; |
||
174 | |||
175 | if (!eglChooseConfig(dpy,config_attribs, &config, 1, &num_configs) || !num_configs) |
||
176 | { |
||
177 | printf("failed to choose a config"); |
||
178 | goto err3; |
||
179 | } |
||
180 | |||
181 | render->context = eglCreateContext(dpy, config, EGL_NO_CONTEXT, NULL); |
||
182 | if (!context) |
||
183 | { |
||
184 | printf("failed to create context"); |
||
185 | goto err3; |
||
186 | }; |
||
187 | |||
188 | if (!eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, render->context)) |
||
189 | { |
||
190 | printf("failed to make window current"); |
||
191 | goto err4; |
||
192 | }; |
||
193 | |||
194 | |||
195 | glGenTextures(2, render->tx_buffers); |
||
196 | if(glGetError() != GL_NO_ERROR) |
||
197 | goto err5; |
||
198 | |||
199 | glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_FRONT]); |
||
200 | if(glGetError() != GL_NO_ERROR) |
||
201 | goto err6; |
||
202 | |||
203 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
||
204 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
||
205 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->front); |
||
206 | if(glGetError() != GL_NO_ERROR) |
||
207 | goto err6; |
||
208 | |||
209 | glBindTexture(GL_TEXTURE_2D, render->tx_buffers[EGL_DRM_BUFFER_BACK]); |
||
210 | if(glGetError() != GL_NO_ERROR) |
||
211 | goto err6; |
||
212 | |||
213 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
||
214 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
||
215 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->back); |
||
216 | if(glGetError() != GL_NO_ERROR) |
||
217 | goto err6; |
||
218 | |||
219 | glBindTexture(GL_TEXTURE_2D, 0); |
||
220 | |||
221 | render->back_buffer = EGL_DRM_BUFFER_BACK; |
||
222 | |||
223 | |||
224 | render->screen = px_create_image(dpy,context,fb.width,fb.height, |
||
225 | fb.pitch,fb.name); |
||
226 | if(render->screen == EGL_NO_IMAGE_KHR) |
||
227 | goto err6; |
||
228 | |||
229 | glGenTextures(1, &render->tx_screen); |
||
230 | if(glGetError() != GL_NO_ERROR) |
||
231 | goto err6; |
||
232 | |||
233 | glBindTexture(GL_TEXTURE_2D, render->tx_screen); |
||
234 | if(glGetError() != GL_NO_ERROR) |
||
235 | goto err7; |
||
236 | |||
237 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); |
||
238 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); |
||
239 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D,render->screen); |
||
240 | if(glGetError() != GL_NO_ERROR) |
||
241 | goto err7; |
||
242 | |||
243 | glBindTexture(GL_TEXTURE_2D, 0); |
||
244 | |||
245 | glGenFramebuffers(1, &render->framebuffer); |
||
246 | if(glGetError() != GL_NO_ERROR) |
||
247 | goto err8; |
||
248 | |||
249 | glBindFramebuffer(GL_FRAMEBUFFER, render->framebuffer); |
||
250 | if(glGetError() != GL_NO_ERROR) |
||
251 | goto err9; |
||
252 | |||
253 | glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, |
||
254 | GL_TEXTURE_2D, render->tx_screen,0); |
||
255 | |||
256 | status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
||
257 | if (status != GL_FRAMEBUFFER_COMPLETE) |
||
258 | { |
||
259 | const char *str; |
||
260 | switch (status) |
||
261 | { |
||
262 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: |
||
263 | str = "incomplete attachment"; |
||
264 | break; |
||
265 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: |
||
266 | str = "incomplete/missing attachment"; |
||
267 | break; |
||
268 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: |
||
269 | str = "incomplete draw buffer"; |
||
270 | break; |
||
271 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: |
||
272 | str = "incomplete read buffer"; |
||
273 | break; |
||
274 | case GL_FRAMEBUFFER_UNSUPPORTED: |
||
275 | str = "unsupported"; |
||
276 | break; |
||
277 | case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: |
||
278 | str = "incomplete multiple"; |
||
279 | break; |
||
280 | default: |
||
281 | str = "unknown error"; |
||
282 | break; |
||
283 | } |
||
284 | printf("destination is framebuffer incomplete: %s [%#x]\n", str, status); |
||
285 | goto err9; |
||
286 | } |
||
287 | |||
288 | glViewport(0, 0, render->scr_width, render->scr_height); |
||
289 | glMatrixMode(GL_PROJECTION); |
||
290 | glLoadIdentity(); |
||
291 | glMatrixMode(GL_MODELVIEW); |
||
292 | glLoadIdentity(); |
||
293 | |||
294 | render->blit_prog = glCreateProgram(); |
||
295 | if(render->blit_prog == 0) |
||
296 | goto err9; |
||
297 | |||
298 | vs_shader = create_shader(GL_VERTEX_SHADER,vs_src); |
||
299 | if(vs_shader == 0) |
||
300 | goto err10; |
||
301 | |||
302 | fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_src); |
||
303 | if(fs_shader == 0) |
||
304 | goto err11; |
||
305 | |||
306 | glAttachShader(render->blit_prog, vs_shader); |
||
307 | glAttachShader(render->blit_prog, fs_shader); |
||
308 | glBindAttribLocation(render->blit_prog, 0, "v_position"); |
||
309 | glBindAttribLocation(render->blit_prog, 1, "v_texcoord0"); |
||
310 | |||
311 | glLinkProgram(render->blit_prog); |
||
312 | glGetProgramiv(render->blit_prog, GL_LINK_STATUS, &ret); |
||
313 | if (!ret) |
||
314 | { |
||
315 | GLchar *info; |
||
316 | GLint size; |
||
317 | |||
318 | glGetProgramiv(render->blit_prog, GL_INFO_LOG_LENGTH, &size); |
||
319 | info = malloc(size); |
||
320 | |||
321 | glGetProgramInfoLog(render->blit_prog, size, NULL, info); |
||
322 | printf("Failed to link: %s\n", info); |
||
323 | printf("GLSL link failure\n"); |
||
324 | free(info); |
||
325 | } |
||
326 | |||
327 | render->sampler = glGetUniformLocation(render->blit_prog,"sampler"); |
||
328 | |||
329 | eglMakeCurrent(dpy, surface, surface, context); |
||
330 | |||
331 | return render; |
||
332 | |||
333 | err11: |
||
334 | glDeleteShader(vs_shader); |
||
335 | err10: |
||
336 | glDeleteProgram(render->blit_prog); |
||
337 | err9: |
||
338 | glDeleteFramebuffers(1, &render->framebuffer); |
||
339 | err8: |
||
340 | eglDestroyImageKHR(dpy, render->screen); |
||
341 | err7: |
||
342 | glDeleteTextures(1, &render->tx_screen); |
||
343 | err6: |
||
344 | glDeleteTextures(2, render->tx_buffers); |
||
345 | err5: |
||
346 | eglMakeCurrent(dpy, surface, surface, context); |
||
347 | err4: |
||
348 | eglDestroyContext(dpy, render->context); |
||
349 | err3: |
||
350 | eglDestroyImageKHR(dpy, render->back); |
||
351 | err2: |
||
352 | eglDestroyImageKHR(dpy, render->front); |
||
353 | err1: |
||
354 | free(render); |
||
355 | err: |
||
356 | return NULL; |
||
357 | }; |
||
358 |