Rev 6142 | Go to most recent revision | Details | Compare with Previous | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
5371 | serge | 1 | #include |
2 | #include |
||
3 | #include |
||
4 | #include |
||
5 | #include |
||
6 | #include "pixlib3.h" |
||
7 | #include "pixdriver.h" |
||
8 | #include "pxgl.h" |
||
9 | |||
10 | #define WIN_STATE_MINIMIZED 0x02 |
||
11 | #define WIN_STATE_ROLLED 0x04 |
||
12 | |||
6137 | serge | 13 | #define LINE() printf("%s line %d\n", __FUNCTION__,__LINE__) |
14 | |||
5371 | serge | 15 | static int drm_ioctl(int fd, unsigned long request, void *arg) |
16 | { |
||
17 | ioctl_t io; |
||
18 | |||
19 | io.handle = fd; |
||
20 | io.io_code = request; |
||
21 | io.input = arg; |
||
22 | io.inp_size = 64; |
||
23 | io.output = NULL; |
||
24 | io.out_size = 0; |
||
25 | |||
26 | return call_service(&io); |
||
27 | } |
||
28 | |||
29 | static EGLImageKHR px_create_image(struct render *px,void *name,GLuint tex, EGLint *attribs) |
||
30 | { |
||
31 | EGLImageKHR image; |
||
32 | |||
33 | image = eglCreateImageKHR(px->dpy, px->context, |
||
34 | EGL_DRM_BUFFER_MESA, name, attribs); |
||
35 | if(image == NULL) |
||
36 | goto err_0; |
||
37 | |||
38 | glBindTexture(GL_TEXTURE_2D, tex); |
||
39 | if(glGetError() != GL_NO_ERROR) |
||
40 | goto err_1; |
||
41 | |||
42 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); |
||
43 | if(glGetError() != GL_NO_ERROR) |
||
44 | goto err_1; |
||
45 | |||
5602 | serge | 46 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); |
47 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); |
||
5371 | serge | 48 | |
49 | return image; |
||
50 | |||
51 | err_1: |
||
52 | eglDestroyImageKHR(px->dpy, image); |
||
53 | err_0: |
||
54 | return NULL; |
||
55 | }; |
||
56 | |||
57 | static int update_fb(struct render *px, int name, int pitch) |
||
58 | { |
||
59 | GLenum status; |
||
60 | EGLImageKHR screen; |
||
61 | |||
62 | EGLint attribs[] = { |
||
63 | EGL_WIDTH, px->scr_width, |
||
64 | EGL_HEIGHT, px->scr_height, |
||
65 | EGL_DRM_BUFFER_STRIDE_MESA, pitch/4, |
||
66 | EGL_DRM_BUFFER_FORMAT_MESA, |
||
67 | EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, |
||
68 | EGL_DRM_BUFFER_USE_MESA, |
||
69 | EGL_DRM_BUFFER_USE_SHARE_MESA | |
||
70 | EGL_DRM_BUFFER_USE_SCANOUT_MESA, |
||
71 | EGL_NONE |
||
72 | }; |
||
73 | char *errmsg; |
||
74 | |||
75 | px->screen = px_create_image(px,(void*)name, px->texture[TEX_SCREEN], attribs); |
||
76 | errmsg = "failed to create new screen image\n"; |
||
77 | if(px->screen == EGL_NO_IMAGE_KHR) |
||
78 | goto err_0; |
||
79 | |||
80 | px->screen = screen; |
||
81 | |||
82 | glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, |
||
83 | GL_TEXTURE_2D, px->texture[TEX_SCREEN],0); |
||
84 | |||
85 | status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
||
86 | if (status != GL_FRAMEBUFFER_COMPLETE) |
||
87 | { |
||
88 | const char *str; |
||
89 | switch (status) |
||
90 | { |
||
91 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: |
||
92 | str = "incomplete attachment"; |
||
93 | break; |
||
94 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: |
||
95 | str = "incomplete/missing attachment"; |
||
96 | break; |
||
97 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: |
||
98 | str = "incomplete draw buffer"; |
||
99 | break; |
||
100 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: |
||
101 | str = "incomplete read buffer"; |
||
102 | break; |
||
103 | case GL_FRAMEBUFFER_UNSUPPORTED: |
||
104 | str = "unsupported"; |
||
105 | break; |
||
106 | case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: |
||
107 | str = "incomplete multiple"; |
||
108 | break; |
||
109 | default: |
||
110 | str = "unknown error"; |
||
111 | break; |
||
112 | } |
||
113 | DBG("destination framebuffer incomplete: %s [%#x]\n", str, status); |
||
114 | |||
115 | return -1; |
||
116 | }; |
||
117 | |||
118 | DBG("framebuffer changed successfull\n"); |
||
119 | |||
120 | glViewport(0, 0, px->scr_width, px->scr_height); |
||
121 | |||
122 | return 0; |
||
123 | |||
124 | err_0: |
||
125 | DBG("%s %s\n", __FUNCTION__, errmsg); |
||
126 | |||
127 | return -1; |
||
128 | }; |
||
129 | |||
130 | |||
131 | |||
132 | static void *px_create_obj(struct render *px, size_t size, |
||
133 | GLuint *handle, GLuint *name) |
||
134 | { |
||
135 | struct drm_i915_gem_create create; |
||
136 | struct drm_i915_gem_mmap mmap_arg; |
||
137 | struct drm_gem_close close; |
||
138 | struct drm_gem_flink flink; |
||
139 | |||
140 | create.size = size; |
||
141 | create.handle = 0; |
||
142 | |||
143 | if(drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_CREATE, &create)) |
||
144 | goto err_0; |
||
145 | |||
146 | *handle = create.handle; |
||
147 | flink.handle = create.handle; |
||
148 | if (drm_ioctl(px->fd, DRM_IOCTL_GEM_FLINK, &flink)) |
||
149 | goto err_1; |
||
150 | |||
151 | *name = flink.name; |
||
152 | |||
153 | mmap_arg.handle = *handle; |
||
154 | mmap_arg.offset = 0; |
||
155 | mmap_arg.size = size; |
||
156 | if (drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg)) |
||
157 | { |
||
158 | DBG("%s: failed to mmap bitmap handle=%d, %d bytes, into CPU domain\n", |
||
159 | __FUNCTION__, *handle, size); |
||
160 | goto err_1; |
||
161 | }; |
||
162 | |||
163 | return (void*)(uintptr_t)mmap_arg.addr_ptr; |
||
164 | |||
165 | err_1: |
||
166 | close.handle = *handle; |
||
167 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
168 | err_0: |
||
169 | return NULL; |
||
170 | }; |
||
171 | |||
172 | static int px_create_bitmap(struct render *px, struct bitmap *bitmap, |
||
173 | size_t size, EGLint format) |
||
174 | { |
||
175 | struct drm_gem_close close; |
||
176 | EGLint attribs[] = { |
||
177 | EGL_WIDTH, bitmap->width, |
||
178 | EGL_HEIGHT, bitmap->height, |
||
179 | EGL_DRM_BUFFER_STRIDE_MESA, 0, |
||
180 | EGL_DRM_BUFFER_FORMAT_MESA, |
||
181 | format, |
||
182 | EGL_DRM_BUFFER_USE_MESA, |
||
183 | EGL_DRM_BUFFER_USE_SHARE_MESA, |
||
184 | EGL_NONE |
||
185 | }; |
||
186 | |||
187 | bitmap->buffer = px_create_obj(px, size, &bitmap->handle, &bitmap->name); |
||
188 | if(bitmap->buffer == NULL) |
||
189 | goto err_0; |
||
190 | |||
191 | switch(format) |
||
192 | { |
||
193 | case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: |
||
194 | attribs[5] = bitmap->pitch/4; |
||
195 | break; |
||
196 | case EGL_DRM_BUFFER_FORMAT_R8_MESA: |
||
197 | attribs[5] = bitmap->pitch; |
||
198 | break; |
||
199 | default: |
||
200 | DBG("%s invalid format %x\n", |
||
201 | __FUNCTION__, format); |
||
202 | goto err_1; |
||
203 | } |
||
204 | |||
205 | bitmap->image = px_create_image(px,(void*)bitmap->name, |
||
206 | bitmap->tex, attribs); |
||
207 | if(bitmap->image == NULL) |
||
208 | goto err_1; |
||
209 | |||
210 | DBG("create bitmap:%p %dx%d pitch:%d\n" |
||
211 | "KHRimage:%p gl_tex:%d handle:%d name:%d\n" |
||
212 | "mapped at %x\n", |
||
213 | bitmap, bitmap->width, bitmap->height, bitmap->pitch, |
||
214 | bitmap->image, bitmap->tex, bitmap->handle, bitmap->name, |
||
215 | bitmap->buffer); |
||
216 | |||
217 | return 0; |
||
218 | |||
219 | err_1: |
||
220 | user_free(bitmap->buffer); |
||
221 | close.handle = bitmap->handle; |
||
222 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
223 | err_0: |
||
224 | return -1; |
||
225 | } |
||
226 | |||
227 | |||
228 | static int create_mask(struct render *px) |
||
229 | { |
||
230 | struct drm_i915_mask_update update; |
||
231 | int pitch; |
||
232 | |||
233 | pitch = (px->width+15) & ~15; |
||
234 | |||
235 | px->mask.width = px->width; |
||
236 | px->mask.height = px->height; |
||
237 | px->mask.pitch = pitch; |
||
238 | px->mask.tex = px->texture[TEX_MASK]; |
||
239 | px->mask_size = pitch * px->height; |
||
240 | |||
241 | if(px_create_bitmap(px, &px->mask, px->mask_size, |
||
242 | EGL_DRM_BUFFER_FORMAT_R8_MESA) == 0) |
||
243 | { |
||
244 | update.handle = px->mask.handle; |
||
245 | update.dx = px->dx; |
||
246 | update.dy = px->dy; |
||
247 | update.width = px->width; |
||
248 | update.height = px->height; |
||
249 | update.bo_pitch = (px->width+15) & ~15; |
||
250 | update.bo_map = (int)px->mask.buffer; |
||
251 | update.forced = 1; |
||
252 | drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update); |
||
253 | return 0; |
||
254 | }; |
||
255 | return -1; |
||
256 | }; |
||
257 | |||
258 | |||
259 | static int update_mask(struct render *px) |
||
260 | { |
||
261 | struct drm_gem_close close; |
||
262 | EGLint attribs[] = { |
||
263 | EGL_WIDTH, 0, |
||
264 | EGL_HEIGHT, 0, |
||
265 | EGL_DRM_BUFFER_STRIDE_MESA, 0, |
||
266 | EGL_DRM_BUFFER_FORMAT_MESA, |
||
267 | EGL_DRM_BUFFER_FORMAT_R8_MESA, |
||
268 | EGL_DRM_BUFFER_USE_MESA, |
||
269 | EGL_DRM_BUFFER_USE_SHARE_MESA, |
||
270 | EGL_NONE |
||
271 | }; |
||
272 | unsigned int size, pitch; |
||
273 | |||
274 | eglDestroyImageKHR(px->dpy, px->mask.image); |
||
275 | |||
276 | pitch = (px->width+15) & ~15; |
||
277 | size = pitch*px->height; |
||
278 | |||
279 | if(size > px->mask_size) |
||
280 | { |
||
281 | user_free(px->mask.buffer); |
||
282 | close.handle = px->mask.handle; |
||
283 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
284 | |||
285 | px->mask_size = size; |
||
286 | |||
287 | px->mask.buffer = px_create_obj(px, px->mask_size, |
||
288 | &px->mask.handle, &px->mask.name); |
||
289 | if(px->mask.buffer == 0) |
||
290 | goto err_0; |
||
291 | }; |
||
292 | |||
293 | attribs[1] = px->width; |
||
294 | attribs[3] = px->height; |
||
295 | attribs[5] = pitch; |
||
296 | |||
297 | px->mask.image = px_create_image(px,(void*)px->mask.name, |
||
298 | px->mask.tex, attribs); |
||
299 | if(px->mask.image == NULL) |
||
300 | goto err_1; |
||
301 | |||
302 | DBG("create mask w:%d h:%d pitch:%d\n" |
||
303 | "KHRimage:%p gl_tex:%d handle:%d name:%d\n" |
||
304 | "mapped at %x\n", |
||
305 | px->width, px->height, |
||
306 | pitch, px->mask.image, px->texture[TEX_MASK], |
||
307 | px->mask.handle, px->mask.name, px->mask.buffer); |
||
308 | |||
309 | return 0; |
||
310 | |||
311 | err_1: |
||
312 | user_free(px->mask.buffer); |
||
313 | close.handle = px->mask.handle; |
||
314 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
315 | err_0: |
||
316 | return -1; |
||
317 | }; |
||
318 | |||
6137 | serge | 319 | static GLint create_shader(GLenum type, const char *source) |
5371 | serge | 320 | { |
6137 | serge | 321 | GLint ok; |
322 | GLint shader; |
||
323 | |||
324 | shader = glCreateShader(type); |
||
325 | if(shader == 0) |
||
326 | goto err; |
||
327 | |||
328 | glShaderSource(shader, 1, (const GLchar **) &source, NULL); |
||
329 | glCompileShader(shader); |
||
330 | glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); |
||
331 | if (!ok) { |
||
332 | GLchar *info; |
||
333 | GLint size; |
||
334 | |||
335 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); |
||
336 | info = malloc(size); |
||
337 | |||
338 | glGetShaderInfoLog(shader, size, NULL, info); |
||
339 | DBG("Failed to compile %s: %s\n", |
||
340 | type == GL_FRAGMENT_SHADER ? "FS" : "VS",info); |
||
341 | DBG("Program source:\n%s", source); |
||
342 | DBG("GLSL compile failure\n"); |
||
343 | free(info); |
||
344 | glDeleteShader(shader); |
||
345 | shader = 0; |
||
346 | }; |
||
347 | |||
348 | DBG("create shader %d\n", shader); |
||
349 | err: |
||
350 | return shader; |
||
351 | } |
||
352 | |||
353 | static GLuint create_rgba_shader(struct shader *shader) |
||
354 | { |
||
5371 | serge | 355 | const char *vs_src = |
356 | "attribute vec4 v_position;\n" |
||
357 | "attribute vec4 v_texcoord0;\n" |
||
6137 | serge | 358 | "varying vec2 tex_coord;\n" |
5371 | serge | 359 | "void main()\n" |
360 | "{\n" |
||
361 | " gl_Position = v_position;\n" |
||
6137 | serge | 362 | " tex_coord = v_texcoord0.xy;\n" |
5371 | serge | 363 | "}\n"; |
364 | |||
6334 | serge | 365 | const char *fs_i965 = |
6137 | serge | 366 | "uniform sampler2D tex_rgba;\n" |
367 | "uniform sampler2D tex_mask;\n" |
||
368 | "varying vec2 tex_coord;\n" |
||
5371 | serge | 369 | "void main()\n" |
370 | "{\n" |
||
6137 | serge | 371 | " float ca = texture2D(tex_mask, tex_coord).r;\n" |
372 | " gl_FragColor = vec4(texture2D(tex_rgba, tex_coord).rgb, ca);\n" |
||
5371 | serge | 373 | "}\n"; |
374 | |||
6334 | serge | 375 | const char *fs_i915 = |
376 | "uniform sampler2D tex_rgba;\n" |
||
377 | "uniform sampler2D tex_mask;\n" |
||
378 | "varying vec2 tex_coord;\n" |
||
379 | "void main()\n" |
||
380 | "{\n" |
||
381 | " float ca = texture2D(tex_mask, tex_coord).a;\n" |
||
382 | " gl_FragColor = vec4(texture2D(tex_rgba, tex_coord).rgb, ca);\n" |
||
383 | "}\n"; |
||
384 | |||
6137 | serge | 385 | GLuint prog; |
386 | GLint vs_shader, fs_shader; |
||
6334 | serge | 387 | const char *fs_src; |
388 | char *drv_name; |
||
6137 | serge | 389 | int ret; |
390 | |||
391 | prog = glCreateProgram(); |
||
392 | if(prog == 0) |
||
393 | goto err; |
||
394 | |||
395 | vs_shader = create_shader(GL_VERTEX_SHADER, vs_src); |
||
396 | if(vs_shader == 0) |
||
397 | goto err; |
||
398 | |||
6334 | serge | 399 | drv_name = (char*)glGetString(0x1F04); |
400 | printf("Render: %s\n", drv_name); |
||
401 | |||
402 | if(strstr(drv_name, "i965")) |
||
403 | fs_src = fs_i965; |
||
404 | else if(strstr(drv_name, "i915")) |
||
405 | fs_src = fs_i915; |
||
406 | else fs_src = NULL; |
||
407 | |||
408 | fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_src); |
||
6137 | serge | 409 | if(fs_shader == 0) |
410 | goto err; |
||
411 | |||
412 | glAttachShader(prog, vs_shader); |
||
413 | glAttachShader(prog, fs_shader); |
||
414 | glBindAttribLocation(prog, 0, "v_position"); |
||
415 | glBindAttribLocation(prog, 1, "v_texcoord0"); |
||
416 | |||
417 | glLinkProgram(prog); |
||
418 | glGetProgramiv(prog, GL_LINK_STATUS, &ret); |
||
419 | if (!ret) |
||
420 | { |
||
421 | GLchar *info; |
||
422 | GLint size; |
||
423 | |||
424 | glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); |
||
425 | info = malloc(size); |
||
426 | |||
427 | glGetProgramInfoLog(prog, size, NULL, info); |
||
428 | DBG("Failed to link: %s\n", info); |
||
429 | DBG("GLSL link failure\n"); |
||
430 | free(info); |
||
431 | goto err; |
||
432 | } |
||
433 | |||
434 | shader->sampler0 = glGetUniformLocation(prog,"tex_rgba"); |
||
435 | shader->sm_mask = glGetUniformLocation(prog,"tex_mask"); |
||
436 | shader->blit_prog = prog; |
||
437 | return prog; |
||
438 | err: |
||
439 | return 0; |
||
440 | } |
||
441 | |||
442 | static GLuint create_y_uv_shader(struct shader *shader) |
||
443 | { |
||
444 | const char *vs_src = |
||
445 | "attribute vec4 v_position;\n" |
||
446 | "attribute vec4 v_texcoord0;\n" |
||
447 | "varying vec2 tex_coord;\n" |
||
448 | "void main()\n" |
||
449 | "{\n" |
||
450 | " gl_Position = v_position;\n" |
||
451 | " tex_coord = v_texcoord0.xy;\n" |
||
452 | "}\n"; |
||
453 | |||
454 | const char *fs_y_uv = |
||
455 | "uniform sampler2D tex_src_y;\n" |
||
456 | "uniform sampler2D tex_src_uv;\n" |
||
457 | "uniform sampler2D tex_mask;\n" |
||
458 | "varying vec2 tex_coord;\n" |
||
459 | "void main()\n" |
||
460 | "{\n" |
||
461 | " float y = 1.16438356 * (texture2D(tex_src_y, tex_coord).x - 0.0625);\n" |
||
462 | " float u = texture2D(tex_src_uv, tex_coord).r - 0.5;\n" |
||
463 | " float v = texture2D(tex_src_uv, tex_coord).g - 0.5;\n" |
||
464 | " gl_FragColor.r = y + 1.59602678 * v;\n" \ |
||
465 | " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \ |
||
466 | " gl_FragColor.b = y + 2.01723214 * u;\n" \ |
||
467 | " gl_FragColor.a = texture2D(tex_mask, tex_coord).r;\n" |
||
468 | "}\n"; |
||
469 | |||
470 | GLuint prog; |
||
471 | GLint vs_shader, fs_shader; |
||
472 | int ret; |
||
473 | |||
474 | prog = glCreateProgram(); |
||
475 | if(prog == 0) |
||
476 | goto err; |
||
477 | |||
478 | vs_shader = create_shader(GL_VERTEX_SHADER, vs_src); |
||
479 | if(vs_shader == 0) |
||
480 | goto err; |
||
481 | |||
482 | fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_y_uv); |
||
483 | if(fs_shader == 0) |
||
484 | goto err; |
||
485 | |||
486 | glAttachShader(prog, vs_shader); |
||
487 | glAttachShader(prog, fs_shader); |
||
488 | glBindAttribLocation(prog, 0, "v_position"); |
||
489 | glBindAttribLocation(prog, 1, "v_texcoord0"); |
||
490 | |||
491 | glLinkProgram(prog); |
||
492 | glGetProgramiv(prog, GL_LINK_STATUS, &ret); |
||
493 | if (!ret) |
||
494 | { |
||
495 | GLchar *info; |
||
496 | GLint size; |
||
497 | |||
498 | glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); |
||
499 | info = malloc(size); |
||
500 | |||
501 | glGetProgramInfoLog(prog, size, NULL, info); |
||
502 | DBG("Failed to link: %s\n", info); |
||
503 | DBG("GLSL link failure\n"); |
||
504 | free(info); |
||
505 | goto err; |
||
506 | } |
||
507 | |||
508 | shader->sampler0 = glGetUniformLocation(prog,"tex_src_y"); |
||
509 | shader->sampler1 = glGetUniformLocation(prog,"tex_src_uv"); |
||
510 | shader->sm_mask = glGetUniformLocation(prog,"tex_mask"); |
||
511 | shader->blit_prog = prog; |
||
512 | return prog; |
||
513 | err: |
||
514 | return 0; |
||
515 | } |
||
516 | |||
517 | static struct render* create_render(EGLDisplay dpy, EGLContext context, int dx, int dy, int w, int h) |
||
518 | { |
||
519 | |||
5371 | serge | 520 | struct drm_i915_fb_info fb; |
521 | struct render *px; |
||
6137 | serge | 522 | |
5371 | serge | 523 | int ret; |
524 | |||
525 | px = (struct render*)malloc(sizeof(struct render)); |
||
526 | if(px == NULL) |
||
527 | goto err_0; |
||
528 | |||
529 | px->fd = get_service("DISPLAY"); |
||
530 | |||
531 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
532 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
533 | { DBG("failed to get framebuffer info\n"); |
||
534 | goto err_1; |
||
535 | }; |
||
536 | |||
537 | px->dpy = dpy; |
||
538 | px->context = context; |
||
539 | px->dx = dx; |
||
540 | px->dy = dy; |
||
541 | px->width = w; |
||
542 | px->height = h; |
||
543 | px->scr_width = fb.width; |
||
544 | px->scr_height = fb.height; |
||
545 | |||
546 | glGenTextures(2, px->texture); |
||
547 | if(glGetError() != GL_NO_ERROR) |
||
548 | goto err_1; |
||
549 | |||
550 | glGenFramebuffers(1, &px->framebuffer); |
||
551 | if(glGetError() != GL_NO_ERROR) |
||
552 | goto err_2; |
||
553 | |||
554 | glBindFramebuffer(GL_FRAMEBUFFER, px->framebuffer); |
||
555 | if(glGetError() != GL_NO_ERROR) |
||
556 | goto err_3; |
||
557 | |||
558 | if(update_fb(px, fb.name, fb.pitch)) |
||
559 | goto err_4; |
||
560 | |||
561 | glMatrixMode(GL_PROJECTION); |
||
562 | glLoadIdentity(); |
||
563 | glMatrixMode(GL_MODELVIEW); |
||
564 | glLoadIdentity(); |
||
565 | |||
566 | if(create_mask(px)) |
||
567 | goto err_4; |
||
568 | |||
6137 | serge | 569 | create_y_uv_shader(&px->shader_y_uv); |
570 | create_rgba_shader(&px->shader_rgba); |
||
5371 | serge | 571 | |
572 | glEnableClientState(GL_VERTEX_ARRAY); |
||
573 | |||
574 | glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->vertices); |
||
575 | glEnableVertexAttribArray(0); |
||
576 | |||
577 | glVertexAttribPointer(1, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->tc_src); |
||
578 | glEnableVertexAttribArray(1); |
||
579 | |||
580 | glEnable(GL_BLEND); |
||
581 | glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); |
||
582 | |||
583 | px->tc_src[0] = 0.0; |
||
584 | px->tc_src[1] = 0.0; |
||
585 | px->tc_src[1*2] = 1.0; |
||
586 | px->tc_src[1*2+1]= 0.0; |
||
587 | px->tc_src[2*2] = 1.0; |
||
588 | px->tc_src[2*2+1]= 1.0; |
||
589 | px->tc_src[3*2] = 0.0; |
||
590 | px->tc_src[3*2+1]= 1.0; |
||
591 | |||
592 | DBG("create render framebuffer:%p %dx%d pitch:%d name %d\n", |
||
593 | px->screen,fb.width, fb.height, fb.pitch, fb.name); |
||
594 | |||
595 | return px; |
||
596 | |||
597 | err_4: |
||
598 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||
599 | err_3: |
||
600 | glDeleteFramebuffers(1, &px->framebuffer); |
||
601 | err_2: |
||
602 | glDeleteTextures(2, px->texture); |
||
603 | err_1: |
||
604 | free(px); |
||
605 | err_0: |
||
606 | return NULL; |
||
607 | }; |
||
608 | |||
609 | static struct render *px; |
||
610 | |||
611 | static bitmap_t *hw_create_bitmap(uint32_t width, uint32_t height) |
||
612 | { |
||
613 | struct bitmap *bitmap; |
||
614 | |||
615 | bitmap = malloc(sizeof(struct bitmap)); |
||
616 | if(bitmap == NULL) |
||
617 | return NULL; |
||
618 | |||
619 | glGenTextures(1, &bitmap->tex); |
||
620 | if(glGetError() != GL_NO_ERROR) |
||
621 | goto err_0; |
||
622 | |||
623 | bitmap->width = width; |
||
624 | bitmap->height = height; |
||
625 | bitmap->pitch = (width*4 + 15) & ~15; |
||
626 | |||
627 | if(px_create_bitmap(px, bitmap, bitmap->pitch * bitmap->height, |
||
628 | EGL_DRM_BUFFER_FORMAT_ARGB32_MESA) == 0) |
||
629 | { |
||
630 | return bitmap; |
||
631 | }; |
||
632 | |||
633 | glDeleteTextures(1, &bitmap->tex); |
||
634 | err_0: |
||
635 | free(bitmap); |
||
636 | return NULL; |
||
637 | }; |
||
638 | |||
6142 | serge | 639 | static int hw_destroy_planar(planar_t *planar) |
640 | { |
||
641 | glDeleteTextures(planar->num_planes, &planar->tex[0]); |
||
642 | |||
643 | if(planar->image[2] != NULL) |
||
644 | eglDestroyImageKHR(px->dpy, planar->image[2]); |
||
645 | if(planar->image[1] != NULL) |
||
646 | eglDestroyImageKHR(px->dpy, planar->image[1]); |
||
647 | if(planar->image[0] != NULL) |
||
648 | eglDestroyImageKHR(px->dpy, planar->image[0]); |
||
649 | if(planar->planar_image != NULL) |
||
650 | eglDestroyImageKHR(px->dpy, planar->planar_image); |
||
651 | free(planar); |
||
652 | return 0; |
||
653 | }; |
||
654 | |||
6115 | serge | 655 | static planar_t* hw_create_planar(EGLint name, EGLint format, uint32_t width, uint32_t height, |
656 | uint32_t offset0, uint32_t pitch0, |
||
657 | uint32_t offset1, uint32_t pitch1, |
||
658 | uint32_t offset2, uint32_t pitch2) |
||
659 | { |
||
660 | struct drm_gem_close close; |
||
661 | planar_t *planar; |
||
662 | EGLImageKHR img; |
||
663 | int num_planes; |
||
664 | int i; |
||
665 | |||
666 | EGLint attribs[] = { |
||
667 | EGL_WIDTH, width, |
||
668 | EGL_HEIGHT,height, |
||
669 | EGL_DRM_BUFFER_FORMAT_MESA, format, |
||
670 | EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset0, |
||
671 | EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch0, |
||
672 | EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset1, |
||
673 | EGL_DMA_BUF_PLANE1_PITCH_EXT, pitch1, |
||
674 | EGL_DMA_BUF_PLANE2_OFFSET_EXT, offset2, |
||
675 | EGL_DMA_BUF_PLANE2_PITCH_EXT, pitch2, |
||
676 | EGL_NONE, EGL_NONE |
||
677 | }; |
||
678 | |||
679 | switch (format) |
||
680 | { |
||
6137 | serge | 681 | case WL_DRM_FORMAT_NV12: |
6115 | serge | 682 | num_planes = 2; |
683 | break; |
||
684 | case EGL_TEXTURE_Y_U_V_WL: |
||
685 | num_planes = 3; |
||
686 | break; |
||
687 | case EGL_TEXTURE_Y_XUXV_WL: |
||
688 | num_planes = 2; |
||
689 | break; |
||
690 | default: |
||
691 | num_planes = 0; |
||
692 | } |
||
693 | |||
6137 | serge | 694 | // printf("%s num_planes %d\n", __FUNCTION__, num_planes); |
695 | |||
6115 | serge | 696 | if(num_planes == 0) |
6137 | serge | 697 | goto fail; |
6115 | serge | 698 | |
699 | planar = calloc(1, sizeof(struct planar)); |
||
700 | if(planar == NULL) |
||
6137 | serge | 701 | goto fail; |
6115 | serge | 702 | |
703 | img = eglCreatePlanarImage(px->dpy, px->context, (EGLClientBuffer)name, attribs); |
||
704 | if(img == NULL) |
||
705 | goto err_0; |
||
706 | |||
707 | planar->width = width; |
||
708 | planar->height = height; |
||
709 | planar->name = name; |
||
6142 | serge | 710 | planar->num_planes = num_planes; |
6115 | serge | 711 | planar->planar_image = img; |
712 | |||
713 | planar->offset[0] = offset0; |
||
714 | planar->offset[1] = offset1; |
||
715 | planar->offset[2] = offset2; |
||
716 | |||
717 | planar->pitch[0] = pitch0; |
||
718 | planar->pitch[1] = pitch1; |
||
719 | planar->pitch[2] = pitch2; |
||
720 | |||
721 | glGenTextures(num_planes, &planar->tex[0]); |
||
6142 | serge | 722 | if(glGetError() != GL_NO_ERROR) |
723 | goto err_0; |
||
6115 | serge | 724 | |
725 | for(i = 0; i < num_planes; i++) |
||
726 | { |
||
6137 | serge | 727 | EGLImageKHR image; |
6115 | serge | 728 | EGLint attr[3]; |
729 | attr[0] = EGL_WAYLAND_PLANE_WL; |
||
730 | attr[1] = i; |
||
731 | attr[2] = EGL_NONE; |
||
732 | |||
6137 | serge | 733 | image = eglCreateImageKHR(px->dpy, px->context, |
734 | EGL_WAYLAND_BUFFER_WL,(EGLClientBuffer)img, attr); |
||
6142 | serge | 735 | if(image == NULL) |
736 | goto err_1; |
||
6115 | serge | 737 | |
6137 | serge | 738 | planar->image[i] = image; |
6115 | serge | 739 | glBindTexture(GL_TEXTURE_2D, planar->tex[i]); |
6137 | serge | 740 | if(glGetError() != GL_NO_ERROR) |
741 | { |
||
6142 | serge | 742 | goto err_1; |
6137 | serge | 743 | }; |
6115 | serge | 744 | |
6137 | serge | 745 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); |
746 | if(glGetError() != GL_NO_ERROR) |
||
747 | { |
||
6142 | serge | 748 | goto err_1; |
6137 | serge | 749 | } |
750 | |||
6115 | serge | 751 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); |
752 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); |
||
753 | }; |
||
754 | |||
755 | return planar; |
||
756 | |||
6142 | serge | 757 | err_1: |
758 | hw_destroy_planar(planar); |
||
759 | return NULL; |
||
760 | |||
6115 | serge | 761 | err_0: |
762 | free(planar); |
||
6137 | serge | 763 | fail: |
6115 | serge | 764 | return NULL; |
765 | } |
||
766 | |||
5371 | serge | 767 | static int hw_destroy_bitmap(bitmap_t * bitmap) |
768 | { |
||
769 | struct drm_gem_close close; |
||
770 | |||
771 | glDeleteTextures(1, &bitmap->tex); |
||
772 | eglDestroyImageKHR(px->dpy, bitmap->image); |
||
773 | user_free(bitmap->buffer); |
||
774 | close.handle = bitmap->handle; |
||
775 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
776 | free(bitmap); |
||
6142 | serge | 777 | return 0; |
5371 | serge | 778 | }; |
779 | |||
780 | static void *hw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch) |
||
781 | { |
||
782 | *pitch = bitmap->pitch; |
||
783 | |||
784 | return bitmap->buffer; |
||
785 | }; |
||
786 | |||
787 | static int hw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height) |
||
788 | { |
||
789 | return 0; |
||
790 | } |
||
791 | |||
792 | char proc_info[1024]; |
||
793 | |||
794 | static int hw_blit(bitmap_t *bitmap, int dst_x, int dst_y, |
||
795 | uint32_t w, uint32_t h, int src_x, int src_y) |
||
796 | { |
||
797 | struct drm_i915_mask_update update; |
||
798 | struct drm_i915_fb_info fb; |
||
799 | |||
800 | uint32_t winx, winy, winw, winh; |
||
801 | uint8_t state; |
||
802 | float xscale, yscale; |
||
803 | int r, b; |
||
804 | float *vertices = px->vertices; |
||
805 | |||
806 | get_proc_info(proc_info); |
||
807 | |||
808 | state = *(uint8_t*)(proc_info+70); |
||
809 | if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED)) |
||
810 | return; |
||
811 | |||
812 | winx = *(uint32_t*)(proc_info+34); |
||
813 | winy = *(uint32_t*)(proc_info+38); |
||
814 | winw = *(uint32_t*)(proc_info+42)+1; |
||
815 | winh = *(uint32_t*)(proc_info+46)+1; |
||
816 | |||
817 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
818 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
819 | { |
||
820 | DBG("failed to get framebuffer info\n"); |
||
821 | return; |
||
822 | }; |
||
823 | |||
824 | if( fb.width != px->scr_width || |
||
825 | fb.height != px->scr_height ) |
||
826 | { |
||
827 | px->scr_width = fb.width; |
||
828 | px->scr_height = fb.height; |
||
829 | |||
830 | eglDestroyImageKHR(px->dpy, px->screen); |
||
831 | |||
832 | if(update_fb(px, fb.name, fb.pitch)) |
||
833 | return; |
||
834 | }; |
||
835 | |||
836 | update.handle = px->mask.handle; |
||
837 | update.dx = px->dx; |
||
838 | update.dy = px->dy; |
||
839 | update.width = px->width; |
||
840 | update.height = px->height; |
||
841 | update.bo_pitch = (px->width+15) & ~15; |
||
842 | update.bo_map = (int)px->mask.buffer; |
||
843 | |||
844 | if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update)) |
||
845 | { |
||
846 | return; |
||
847 | } |
||
848 | |||
849 | xscale = 1.0/px->scr_width; |
||
850 | yscale = 1.0/px->scr_height; |
||
851 | |||
852 | r = winx + px->dx + px->width; |
||
853 | b = winy + px->dy + px->height; |
||
854 | |||
855 | float t0, t1, t2, t5; |
||
856 | |||
857 | // render->tc_src[1*2] = 1.0; |
||
858 | // render->tc_src[2*2] = 1.0; |
||
859 | // render->tc_src[2*2+1]= 1.0; |
||
860 | // render->tc_src[3*2+1]= 1.0; |
||
861 | |||
862 | vertices[0] = t0 = 2*(winx+px->dx)*xscale - 1.0; |
||
863 | vertices[1 * 2] = t2 = 2*r*xscale - 1.0; |
||
864 | |||
865 | vertices[2 * 2] = t2; |
||
866 | vertices[3 * 2] = t0; |
||
867 | |||
868 | vertices[1] = t1 = 2*(winy+px->dy)*yscale - 1.0; |
||
869 | vertices[2*2+1] = t5 = 2*b*yscale - 1.0; |
||
870 | vertices[1*2+1] = t1; |
||
871 | vertices[3*2+1] = t5; |
||
872 | |||
6137 | serge | 873 | struct shader *shader = &px->shader_rgba; |
874 | |||
875 | glUseProgram(shader->blit_prog); |
||
876 | glUniform1i(shader->sampler0, 0); |
||
877 | glUniform1i(shader->sm_mask, 1); |
||
878 | |||
5371 | serge | 879 | glActiveTexture(GL_TEXTURE0); |
880 | glBindTexture(GL_TEXTURE_2D, bitmap->tex); |
||
881 | |||
882 | glActiveTexture(GL_TEXTURE1); |
||
883 | glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]); |
||
884 | |||
885 | glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
||
886 | |||
887 | glFlush(); |
||
888 | |||
889 | return; |
||
890 | }; |
||
891 | |||
6137 | serge | 892 | static int hw_blit_planar(planar_t *planar, int dst_x, int dst_y, |
893 | uint32_t w, uint32_t h, int src_x, int src_y) |
||
894 | { |
||
895 | struct drm_i915_mask_update update; |
||
896 | struct drm_i915_fb_info fb; |
||
897 | |||
898 | uint32_t winx, winy, winw, winh; |
||
899 | uint8_t state; |
||
900 | float xscale, yscale; |
||
901 | int r, b; |
||
902 | float *vertices = px->vertices; |
||
903 | |||
904 | get_proc_info(proc_info); |
||
905 | |||
906 | state = *(uint8_t*)(proc_info+70); |
||
907 | if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED)) |
||
908 | return; |
||
909 | |||
910 | winx = *(uint32_t*)(proc_info+34); |
||
911 | winy = *(uint32_t*)(proc_info+38); |
||
912 | winw = *(uint32_t*)(proc_info+42)+1; |
||
913 | winh = *(uint32_t*)(proc_info+46)+1; |
||
914 | |||
915 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
916 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
917 | { |
||
918 | DBG("failed to get framebuffer info\n"); |
||
919 | return; |
||
920 | }; |
||
921 | |||
922 | if( fb.width != px->scr_width || |
||
923 | fb.height != px->scr_height ) |
||
924 | { |
||
925 | px->scr_width = fb.width; |
||
926 | px->scr_height = fb.height; |
||
927 | |||
928 | eglDestroyImageKHR(px->dpy, px->screen); |
||
929 | |||
930 | if(update_fb(px, fb.name, fb.pitch)) |
||
931 | return; |
||
932 | }; |
||
933 | |||
934 | update.handle = px->mask.handle; |
||
935 | update.dx = px->dx; |
||
936 | update.dy = px->dy; |
||
937 | update.width = px->width; |
||
938 | update.height = px->height; |
||
939 | update.bo_pitch = (px->width+15) & ~15; |
||
940 | update.bo_map = (int)px->mask.buffer; |
||
941 | |||
942 | if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update)) |
||
943 | { |
||
944 | return; |
||
945 | } |
||
946 | |||
947 | xscale = 1.0/px->scr_width; |
||
948 | yscale = 1.0/px->scr_height; |
||
949 | |||
950 | r = winx + px->dx + px->width; |
||
951 | b = winy + px->dy + px->height; |
||
952 | |||
953 | float t0, t1, t2, t5; |
||
954 | |||
955 | // render->tc_src[1*2] = 1.0; |
||
956 | // render->tc_src[2*2] = 1.0; |
||
957 | // render->tc_src[2*2+1]= 1.0; |
||
958 | // render->tc_src[3*2+1]= 1.0; |
||
959 | |||
960 | vertices[0] = t0 = 2*(winx+px->dx)*xscale - 1.0; |
||
961 | vertices[1 * 2] = t2 = 2*r*xscale - 1.0; |
||
962 | |||
963 | vertices[2 * 2] = t2; |
||
964 | vertices[3 * 2] = t0; |
||
965 | |||
966 | vertices[1] = t1 = 2*(winy+px->dy)*yscale - 1.0; |
||
967 | vertices[2*2+1] = t5 = 2*b*yscale - 1.0; |
||
968 | vertices[1*2+1] = t1; |
||
969 | vertices[3*2+1] = t5; |
||
970 | |||
971 | struct shader *shader = &px->shader_y_uv; |
||
972 | |||
973 | glUseProgram(shader->blit_prog); |
||
974 | glUniform1i(shader->sampler0, 0); |
||
975 | glUniform1i(shader->sampler1, 1); |
||
976 | glUniform1i(shader->sm_mask, 2); |
||
977 | |||
978 | glActiveTexture(GL_TEXTURE0); |
||
979 | glBindTexture(GL_TEXTURE_2D, planar->tex[0]); |
||
980 | |||
981 | glActiveTexture(GL_TEXTURE1); |
||
982 | glBindTexture(GL_TEXTURE_2D, planar->tex[1]); |
||
983 | |||
984 | glActiveTexture(GL_TEXTURE2); |
||
985 | glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]); |
||
986 | |||
987 | glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
||
988 | |||
989 | glFlush(); |
||
990 | |||
991 | return; |
||
992 | }; |
||
993 | |||
5371 | serge | 994 | static int hw_create_client(int x, int y, uint32_t width, uint32_t height) |
995 | { |
||
996 | px = create_render(eglGetCurrentDisplay(), eglGetCurrentContext(), x, y, width, height); |
||
997 | |||
998 | return !px; |
||
999 | }; |
||
1000 | |||
1001 | static int hw_resize_client(int x, int y, uint32_t width, uint32_t height) |
||
1002 | { |
||
1003 | if( x != px->dx || |
||
1004 | y != px->dy || |
||
1005 | width != px->width || |
||
1006 | height != px->height ) |
||
1007 | { |
||
1008 | struct drm_i915_mask_update update; |
||
1009 | |||
1010 | px->dx = x; |
||
1011 | px->dy = y; |
||
1012 | px->width = width; |
||
1013 | px->height = height; |
||
1014 | update_mask(px); |
||
1015 | |||
1016 | update.handle = px->mask.handle; |
||
1017 | update.dx = px->dx; |
||
1018 | update.dy = px->dy; |
||
1019 | update.width = px->width; |
||
1020 | update.height = px->height; |
||
1021 | update.bo_pitch = (px->width+15) & ~15; |
||
1022 | update.bo_map = (int)px->mask.buffer; |
||
1023 | update.forced = 1; |
||
1024 | |||
1025 | drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update); |
||
1026 | }; |
||
1027 | |||
1028 | return 0; |
||
1029 | }; |
||
1030 | |||
1031 | static void hw_fini(void) |
||
1032 | { |
||
1033 | struct drm_gem_close close; |
||
1034 | |||
1035 | DBG("%s\n", __FUNCTION__); |
||
1036 | |||
1037 | eglDestroyImageKHR(px->dpy, px->mask.image); |
||
1038 | user_free(px->mask.buffer); |
||
1039 | close.handle = px->mask.handle; |
||
1040 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
1041 | |||
1042 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||
1043 | glDeleteFramebuffers(1, &px->framebuffer); |
||
1044 | eglDestroyImageKHR(px->dpy, px->screen); |
||
1045 | glDeleteTextures(2, px->texture); |
||
1046 | egl_destroy(px->dpy, px->context); |
||
1047 | free(px); |
||
1048 | }; |
||
1049 | |||
1050 | static struct pix_driver gl_driver = |
||
1051 | { |
||
1052 | HW_TEX_BLIT, |
||
1053 | hw_create_bitmap, |
||
1054 | hw_destroy_bitmap, |
||
1055 | hw_lock_bitmap, |
||
1056 | hw_resize_bitmap, |
||
1057 | hw_blit, |
||
1058 | hw_create_client, |
||
1059 | hw_resize_client, |
||
6115 | serge | 1060 | hw_fini, |
6137 | serge | 1061 | hw_create_planar, |
6142 | serge | 1062 | hw_destroy_planar, |
6137 | serge | 1063 | hw_blit_planar |
5371 | serge | 1064 | }; |
1065 | |||
1066 | struct pix_driver *DrvInit(uint32_t service) |
||
1067 | { |
||
1068 | EGLDisplay dpy; |
||
1069 | EGLConfig config; |
||
1070 | EGLContext context; |
||
1071 | int ret; |
||
1072 | |||
1073 | ret = egl_initialize(&dpy, &config, &context); |
||
1074 | if( ret ) |
||
1075 | return NULL; |
||
1076 | |||
1077 | return &gl_driver; |
||
1078 | |||
1079 | err_0: |
||
1080 | egl_destroy(dpy, context); |
||
1081 | return NULL; |
||
1082 | }> |
||
1083 |