Rev 6115 | 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 | |||
6137 | serge | 365 | const char *fs_rgba = |
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 | |||
6137 | serge | 375 | GLuint prog; |
376 | GLint vs_shader, fs_shader; |
||
377 | int ret; |
||
378 | |||
379 | prog = glCreateProgram(); |
||
380 | if(prog == 0) |
||
381 | goto err; |
||
382 | |||
383 | vs_shader = create_shader(GL_VERTEX_SHADER, vs_src); |
||
384 | if(vs_shader == 0) |
||
385 | goto err; |
||
386 | |||
387 | fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_rgba); |
||
388 | if(fs_shader == 0) |
||
389 | goto err; |
||
390 | |||
391 | glAttachShader(prog, vs_shader); |
||
392 | glAttachShader(prog, fs_shader); |
||
393 | glBindAttribLocation(prog, 0, "v_position"); |
||
394 | glBindAttribLocation(prog, 1, "v_texcoord0"); |
||
395 | |||
396 | glLinkProgram(prog); |
||
397 | glGetProgramiv(prog, GL_LINK_STATUS, &ret); |
||
398 | if (!ret) |
||
399 | { |
||
400 | GLchar *info; |
||
401 | GLint size; |
||
402 | |||
403 | glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); |
||
404 | info = malloc(size); |
||
405 | |||
406 | glGetProgramInfoLog(prog, size, NULL, info); |
||
407 | DBG("Failed to link: %s\n", info); |
||
408 | DBG("GLSL link failure\n"); |
||
409 | free(info); |
||
410 | goto err; |
||
411 | } |
||
412 | |||
413 | shader->sampler0 = glGetUniformLocation(prog,"tex_rgba"); |
||
414 | shader->sm_mask = glGetUniformLocation(prog,"tex_mask"); |
||
415 | shader->blit_prog = prog; |
||
416 | return prog; |
||
417 | err: |
||
418 | return 0; |
||
419 | } |
||
420 | |||
421 | static GLuint create_y_uv_shader(struct shader *shader) |
||
422 | { |
||
423 | const char *vs_src = |
||
424 | "attribute vec4 v_position;\n" |
||
425 | "attribute vec4 v_texcoord0;\n" |
||
426 | "varying vec2 tex_coord;\n" |
||
427 | "void main()\n" |
||
428 | "{\n" |
||
429 | " gl_Position = v_position;\n" |
||
430 | " tex_coord = v_texcoord0.xy;\n" |
||
431 | "}\n"; |
||
432 | |||
433 | const char *fs_y_uv = |
||
434 | "uniform sampler2D tex_src_y;\n" |
||
435 | "uniform sampler2D tex_src_uv;\n" |
||
436 | "uniform sampler2D tex_mask;\n" |
||
437 | "varying vec2 tex_coord;\n" |
||
438 | "void main()\n" |
||
439 | "{\n" |
||
440 | " float y = 1.16438356 * (texture2D(tex_src_y, tex_coord).x - 0.0625);\n" |
||
441 | " float u = texture2D(tex_src_uv, tex_coord).r - 0.5;\n" |
||
442 | " float v = texture2D(tex_src_uv, tex_coord).g - 0.5;\n" |
||
443 | " gl_FragColor.r = y + 1.59602678 * v;\n" \ |
||
444 | " gl_FragColor.g = y - 0.39176229 * u - 0.81296764 * v;\n" \ |
||
445 | " gl_FragColor.b = y + 2.01723214 * u;\n" \ |
||
446 | " gl_FragColor.a = texture2D(tex_mask, tex_coord).r;\n" |
||
447 | "}\n"; |
||
448 | |||
449 | GLuint prog; |
||
450 | GLint vs_shader, fs_shader; |
||
451 | int ret; |
||
452 | |||
453 | prog = glCreateProgram(); |
||
454 | if(prog == 0) |
||
455 | goto err; |
||
456 | |||
457 | vs_shader = create_shader(GL_VERTEX_SHADER, vs_src); |
||
458 | if(vs_shader == 0) |
||
459 | goto err; |
||
460 | |||
461 | fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_y_uv); |
||
462 | if(fs_shader == 0) |
||
463 | goto err; |
||
464 | |||
465 | glAttachShader(prog, vs_shader); |
||
466 | glAttachShader(prog, fs_shader); |
||
467 | glBindAttribLocation(prog, 0, "v_position"); |
||
468 | glBindAttribLocation(prog, 1, "v_texcoord0"); |
||
469 | |||
470 | glLinkProgram(prog); |
||
471 | glGetProgramiv(prog, GL_LINK_STATUS, &ret); |
||
472 | if (!ret) |
||
473 | { |
||
474 | GLchar *info; |
||
475 | GLint size; |
||
476 | |||
477 | glGetProgramiv(prog, GL_INFO_LOG_LENGTH, &size); |
||
478 | info = malloc(size); |
||
479 | |||
480 | glGetProgramInfoLog(prog, size, NULL, info); |
||
481 | DBG("Failed to link: %s\n", info); |
||
482 | DBG("GLSL link failure\n"); |
||
483 | free(info); |
||
484 | goto err; |
||
485 | } |
||
486 | |||
487 | shader->sampler0 = glGetUniformLocation(prog,"tex_src_y"); |
||
488 | shader->sampler1 = glGetUniformLocation(prog,"tex_src_uv"); |
||
489 | shader->sm_mask = glGetUniformLocation(prog,"tex_mask"); |
||
490 | shader->blit_prog = prog; |
||
491 | return prog; |
||
492 | err: |
||
493 | return 0; |
||
494 | } |
||
495 | |||
496 | static struct render* create_render(EGLDisplay dpy, EGLContext context, int dx, int dy, int w, int h) |
||
497 | { |
||
498 | |||
5371 | serge | 499 | struct drm_i915_fb_info fb; |
500 | struct render *px; |
||
6137 | serge | 501 | |
5371 | serge | 502 | int ret; |
503 | |||
504 | px = (struct render*)malloc(sizeof(struct render)); |
||
505 | if(px == NULL) |
||
506 | goto err_0; |
||
507 | |||
508 | px->fd = get_service("DISPLAY"); |
||
509 | |||
510 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
511 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
512 | { DBG("failed to get framebuffer info\n"); |
||
513 | goto err_1; |
||
514 | }; |
||
515 | |||
516 | px->dpy = dpy; |
||
517 | px->context = context; |
||
518 | px->dx = dx; |
||
519 | px->dy = dy; |
||
520 | px->width = w; |
||
521 | px->height = h; |
||
522 | px->scr_width = fb.width; |
||
523 | px->scr_height = fb.height; |
||
524 | |||
525 | glGenTextures(2, px->texture); |
||
526 | if(glGetError() != GL_NO_ERROR) |
||
527 | goto err_1; |
||
528 | |||
529 | glGenFramebuffers(1, &px->framebuffer); |
||
530 | if(glGetError() != GL_NO_ERROR) |
||
531 | goto err_2; |
||
532 | |||
533 | glBindFramebuffer(GL_FRAMEBUFFER, px->framebuffer); |
||
534 | if(glGetError() != GL_NO_ERROR) |
||
535 | goto err_3; |
||
536 | |||
537 | if(update_fb(px, fb.name, fb.pitch)) |
||
538 | goto err_4; |
||
539 | |||
540 | glMatrixMode(GL_PROJECTION); |
||
541 | glLoadIdentity(); |
||
542 | glMatrixMode(GL_MODELVIEW); |
||
543 | glLoadIdentity(); |
||
544 | |||
545 | if(create_mask(px)) |
||
546 | goto err_4; |
||
547 | |||
6137 | serge | 548 | create_y_uv_shader(&px->shader_y_uv); |
549 | create_rgba_shader(&px->shader_rgba); |
||
5371 | serge | 550 | |
551 | glEnableClientState(GL_VERTEX_ARRAY); |
||
552 | |||
553 | glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->vertices); |
||
554 | glEnableVertexAttribArray(0); |
||
555 | |||
556 | glVertexAttribPointer(1, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->tc_src); |
||
557 | glEnableVertexAttribArray(1); |
||
558 | |||
559 | glEnable(GL_BLEND); |
||
560 | glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); |
||
561 | |||
562 | px->tc_src[0] = 0.0; |
||
563 | px->tc_src[1] = 0.0; |
||
564 | px->tc_src[1*2] = 1.0; |
||
565 | px->tc_src[1*2+1]= 0.0; |
||
566 | px->tc_src[2*2] = 1.0; |
||
567 | px->tc_src[2*2+1]= 1.0; |
||
568 | px->tc_src[3*2] = 0.0; |
||
569 | px->tc_src[3*2+1]= 1.0; |
||
570 | |||
571 | DBG("create render framebuffer:%p %dx%d pitch:%d name %d\n", |
||
572 | px->screen,fb.width, fb.height, fb.pitch, fb.name); |
||
573 | |||
574 | return px; |
||
575 | |||
576 | err_4: |
||
577 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||
578 | err_3: |
||
579 | glDeleteFramebuffers(1, &px->framebuffer); |
||
580 | err_2: |
||
581 | glDeleteTextures(2, px->texture); |
||
582 | err_1: |
||
583 | free(px); |
||
584 | err_0: |
||
585 | return NULL; |
||
586 | }; |
||
587 | |||
588 | static struct render *px; |
||
589 | |||
590 | static bitmap_t *hw_create_bitmap(uint32_t width, uint32_t height) |
||
591 | { |
||
592 | struct bitmap *bitmap; |
||
593 | |||
594 | bitmap = malloc(sizeof(struct bitmap)); |
||
595 | if(bitmap == NULL) |
||
596 | return NULL; |
||
597 | |||
598 | glGenTextures(1, &bitmap->tex); |
||
599 | if(glGetError() != GL_NO_ERROR) |
||
600 | goto err_0; |
||
601 | |||
602 | bitmap->width = width; |
||
603 | bitmap->height = height; |
||
604 | bitmap->pitch = (width*4 + 15) & ~15; |
||
605 | |||
606 | if(px_create_bitmap(px, bitmap, bitmap->pitch * bitmap->height, |
||
607 | EGL_DRM_BUFFER_FORMAT_ARGB32_MESA) == 0) |
||
608 | { |
||
609 | return bitmap; |
||
610 | }; |
||
611 | |||
612 | glDeleteTextures(1, &bitmap->tex); |
||
613 | err_0: |
||
614 | free(bitmap); |
||
615 | return NULL; |
||
616 | }; |
||
617 | |||
6115 | serge | 618 | static planar_t* hw_create_planar(EGLint name, EGLint format, uint32_t width, uint32_t height, |
619 | uint32_t offset0, uint32_t pitch0, |
||
620 | uint32_t offset1, uint32_t pitch1, |
||
621 | uint32_t offset2, uint32_t pitch2) |
||
622 | { |
||
623 | struct drm_gem_close close; |
||
624 | planar_t *planar; |
||
625 | EGLImageKHR img; |
||
626 | int num_planes; |
||
627 | int i; |
||
628 | |||
629 | EGLint attribs[] = { |
||
630 | EGL_WIDTH, width, |
||
631 | EGL_HEIGHT,height, |
||
632 | EGL_DRM_BUFFER_FORMAT_MESA, format, |
||
633 | EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset0, |
||
634 | EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch0, |
||
635 | EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset1, |
||
636 | EGL_DMA_BUF_PLANE1_PITCH_EXT, pitch1, |
||
637 | EGL_DMA_BUF_PLANE2_OFFSET_EXT, offset2, |
||
638 | EGL_DMA_BUF_PLANE2_PITCH_EXT, pitch2, |
||
639 | EGL_NONE, EGL_NONE |
||
640 | }; |
||
641 | |||
642 | switch (format) |
||
643 | { |
||
6137 | serge | 644 | case WL_DRM_FORMAT_NV12: |
6115 | serge | 645 | num_planes = 2; |
646 | break; |
||
647 | case EGL_TEXTURE_Y_U_V_WL: |
||
648 | num_planes = 3; |
||
649 | break; |
||
650 | case EGL_TEXTURE_Y_XUXV_WL: |
||
651 | num_planes = 2; |
||
652 | break; |
||
653 | default: |
||
654 | num_planes = 0; |
||
655 | } |
||
656 | |||
6137 | serge | 657 | // printf("%s num_planes %d\n", __FUNCTION__, num_planes); |
658 | |||
6115 | serge | 659 | if(num_planes == 0) |
6137 | serge | 660 | goto fail; |
6115 | serge | 661 | |
662 | planar = calloc(1, sizeof(struct planar)); |
||
663 | if(planar == NULL) |
||
6137 | serge | 664 | goto fail; |
6115 | serge | 665 | |
666 | img = eglCreatePlanarImage(px->dpy, px->context, (EGLClientBuffer)name, attribs); |
||
667 | if(img == NULL) |
||
668 | goto err_0; |
||
669 | |||
670 | planar->width = width; |
||
671 | planar->height = height; |
||
672 | planar->name = name; |
||
673 | planar->planar_image = img; |
||
674 | |||
675 | planar->offset[0] = offset0; |
||
676 | planar->offset[1] = offset1; |
||
677 | planar->offset[2] = offset2; |
||
678 | |||
679 | planar->pitch[0] = pitch0; |
||
680 | planar->pitch[1] = pitch1; |
||
681 | planar->pitch[2] = pitch2; |
||
682 | |||
683 | glGenTextures(num_planes, &planar->tex[0]); |
||
684 | |||
685 | for(i = 0; i < num_planes; i++) |
||
686 | { |
||
6137 | serge | 687 | EGLImageKHR image; |
6115 | serge | 688 | EGLint attr[3]; |
689 | attr[0] = EGL_WAYLAND_PLANE_WL; |
||
690 | attr[1] = i; |
||
691 | attr[2] = EGL_NONE; |
||
692 | |||
6137 | serge | 693 | image = eglCreateImageKHR(px->dpy, px->context, |
694 | EGL_WAYLAND_BUFFER_WL,(EGLClientBuffer)img, attr); |
||
6115 | serge | 695 | |
6137 | serge | 696 | planar->image[i] = image; |
6115 | serge | 697 | glBindTexture(GL_TEXTURE_2D, planar->tex[i]); |
698 | |||
6137 | serge | 699 | if(glGetError() != GL_NO_ERROR) |
700 | { |
||
701 | goto fail; |
||
702 | }; |
||
6115 | serge | 703 | |
6137 | serge | 704 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); |
705 | if(glGetError() != GL_NO_ERROR) |
||
706 | { |
||
707 | goto fail; |
||
708 | } |
||
709 | |||
6115 | serge | 710 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); |
711 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); |
||
712 | }; |
||
713 | |||
714 | return planar; |
||
715 | |||
716 | err_0: |
||
717 | free(planar); |
||
6137 | serge | 718 | fail: |
6115 | serge | 719 | |
720 | return NULL; |
||
721 | } |
||
722 | |||
723 | |||
5371 | serge | 724 | static int hw_destroy_bitmap(bitmap_t * bitmap) |
725 | { |
||
726 | struct drm_gem_close close; |
||
727 | |||
728 | glDeleteTextures(1, &bitmap->tex); |
||
729 | eglDestroyImageKHR(px->dpy, bitmap->image); |
||
730 | user_free(bitmap->buffer); |
||
731 | close.handle = bitmap->handle; |
||
732 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
733 | free(bitmap); |
||
734 | }; |
||
735 | |||
736 | static void *hw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch) |
||
737 | { |
||
738 | *pitch = bitmap->pitch; |
||
739 | |||
740 | return bitmap->buffer; |
||
741 | }; |
||
742 | |||
743 | static int hw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height) |
||
744 | { |
||
745 | return 0; |
||
746 | } |
||
747 | |||
748 | char proc_info[1024]; |
||
749 | |||
750 | static int hw_blit(bitmap_t *bitmap, int dst_x, int dst_y, |
||
751 | uint32_t w, uint32_t h, int src_x, int src_y) |
||
752 | { |
||
753 | struct drm_i915_mask_update update; |
||
754 | struct drm_i915_fb_info fb; |
||
755 | |||
756 | uint32_t winx, winy, winw, winh; |
||
757 | uint8_t state; |
||
758 | float xscale, yscale; |
||
759 | int r, b; |
||
760 | float *vertices = px->vertices; |
||
761 | |||
762 | get_proc_info(proc_info); |
||
763 | |||
764 | state = *(uint8_t*)(proc_info+70); |
||
765 | if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED)) |
||
766 | return; |
||
767 | |||
768 | winx = *(uint32_t*)(proc_info+34); |
||
769 | winy = *(uint32_t*)(proc_info+38); |
||
770 | winw = *(uint32_t*)(proc_info+42)+1; |
||
771 | winh = *(uint32_t*)(proc_info+46)+1; |
||
772 | |||
773 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
774 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
775 | { |
||
776 | DBG("failed to get framebuffer info\n"); |
||
777 | return; |
||
778 | }; |
||
779 | |||
780 | if( fb.width != px->scr_width || |
||
781 | fb.height != px->scr_height ) |
||
782 | { |
||
783 | px->scr_width = fb.width; |
||
784 | px->scr_height = fb.height; |
||
785 | |||
786 | eglDestroyImageKHR(px->dpy, px->screen); |
||
787 | |||
788 | if(update_fb(px, fb.name, fb.pitch)) |
||
789 | return; |
||
790 | }; |
||
791 | |||
792 | update.handle = px->mask.handle; |
||
793 | update.dx = px->dx; |
||
794 | update.dy = px->dy; |
||
795 | update.width = px->width; |
||
796 | update.height = px->height; |
||
797 | update.bo_pitch = (px->width+15) & ~15; |
||
798 | update.bo_map = (int)px->mask.buffer; |
||
799 | |||
800 | if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update)) |
||
801 | { |
||
802 | return; |
||
803 | } |
||
804 | |||
805 | xscale = 1.0/px->scr_width; |
||
806 | yscale = 1.0/px->scr_height; |
||
807 | |||
808 | r = winx + px->dx + px->width; |
||
809 | b = winy + px->dy + px->height; |
||
810 | |||
811 | float t0, t1, t2, t5; |
||
812 | |||
813 | // render->tc_src[1*2] = 1.0; |
||
814 | // render->tc_src[2*2] = 1.0; |
||
815 | // render->tc_src[2*2+1]= 1.0; |
||
816 | // render->tc_src[3*2+1]= 1.0; |
||
817 | |||
818 | vertices[0] = t0 = 2*(winx+px->dx)*xscale - 1.0; |
||
819 | vertices[1 * 2] = t2 = 2*r*xscale - 1.0; |
||
820 | |||
821 | vertices[2 * 2] = t2; |
||
822 | vertices[3 * 2] = t0; |
||
823 | |||
824 | vertices[1] = t1 = 2*(winy+px->dy)*yscale - 1.0; |
||
825 | vertices[2*2+1] = t5 = 2*b*yscale - 1.0; |
||
826 | vertices[1*2+1] = t1; |
||
827 | vertices[3*2+1] = t5; |
||
828 | |||
6137 | serge | 829 | struct shader *shader = &px->shader_rgba; |
830 | |||
831 | glUseProgram(shader->blit_prog); |
||
832 | glUniform1i(shader->sampler0, 0); |
||
833 | glUniform1i(shader->sm_mask, 1); |
||
834 | |||
5371 | serge | 835 | glActiveTexture(GL_TEXTURE0); |
836 | glBindTexture(GL_TEXTURE_2D, bitmap->tex); |
||
837 | |||
838 | glActiveTexture(GL_TEXTURE1); |
||
839 | glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]); |
||
840 | |||
841 | glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
||
842 | |||
843 | glFlush(); |
||
844 | |||
845 | return; |
||
846 | }; |
||
847 | |||
6137 | serge | 848 | static int hw_blit_planar(planar_t *planar, int dst_x, int dst_y, |
849 | uint32_t w, uint32_t h, int src_x, int src_y) |
||
850 | { |
||
851 | struct drm_i915_mask_update update; |
||
852 | struct drm_i915_fb_info fb; |
||
853 | |||
854 | uint32_t winx, winy, winw, winh; |
||
855 | uint8_t state; |
||
856 | float xscale, yscale; |
||
857 | int r, b; |
||
858 | float *vertices = px->vertices; |
||
859 | |||
860 | get_proc_info(proc_info); |
||
861 | |||
862 | state = *(uint8_t*)(proc_info+70); |
||
863 | if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED)) |
||
864 | return; |
||
865 | |||
866 | winx = *(uint32_t*)(proc_info+34); |
||
867 | winy = *(uint32_t*)(proc_info+38); |
||
868 | winw = *(uint32_t*)(proc_info+42)+1; |
||
869 | winh = *(uint32_t*)(proc_info+46)+1; |
||
870 | |||
871 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
872 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
873 | { |
||
874 | DBG("failed to get framebuffer info\n"); |
||
875 | return; |
||
876 | }; |
||
877 | |||
878 | if( fb.width != px->scr_width || |
||
879 | fb.height != px->scr_height ) |
||
880 | { |
||
881 | px->scr_width = fb.width; |
||
882 | px->scr_height = fb.height; |
||
883 | |||
884 | eglDestroyImageKHR(px->dpy, px->screen); |
||
885 | |||
886 | if(update_fb(px, fb.name, fb.pitch)) |
||
887 | return; |
||
888 | }; |
||
889 | |||
890 | update.handle = px->mask.handle; |
||
891 | update.dx = px->dx; |
||
892 | update.dy = px->dy; |
||
893 | update.width = px->width; |
||
894 | update.height = px->height; |
||
895 | update.bo_pitch = (px->width+15) & ~15; |
||
896 | update.bo_map = (int)px->mask.buffer; |
||
897 | |||
898 | if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update)) |
||
899 | { |
||
900 | return; |
||
901 | } |
||
902 | |||
903 | xscale = 1.0/px->scr_width; |
||
904 | yscale = 1.0/px->scr_height; |
||
905 | |||
906 | r = winx + px->dx + px->width; |
||
907 | b = winy + px->dy + px->height; |
||
908 | |||
909 | float t0, t1, t2, t5; |
||
910 | |||
911 | // render->tc_src[1*2] = 1.0; |
||
912 | // render->tc_src[2*2] = 1.0; |
||
913 | // render->tc_src[2*2+1]= 1.0; |
||
914 | // render->tc_src[3*2+1]= 1.0; |
||
915 | |||
916 | vertices[0] = t0 = 2*(winx+px->dx)*xscale - 1.0; |
||
917 | vertices[1 * 2] = t2 = 2*r*xscale - 1.0; |
||
918 | |||
919 | vertices[2 * 2] = t2; |
||
920 | vertices[3 * 2] = t0; |
||
921 | |||
922 | vertices[1] = t1 = 2*(winy+px->dy)*yscale - 1.0; |
||
923 | vertices[2*2+1] = t5 = 2*b*yscale - 1.0; |
||
924 | vertices[1*2+1] = t1; |
||
925 | vertices[3*2+1] = t5; |
||
926 | |||
927 | struct shader *shader = &px->shader_y_uv; |
||
928 | |||
929 | glUseProgram(shader->blit_prog); |
||
930 | glUniform1i(shader->sampler0, 0); |
||
931 | glUniform1i(shader->sampler1, 1); |
||
932 | glUniform1i(shader->sm_mask, 2); |
||
933 | |||
934 | glActiveTexture(GL_TEXTURE0); |
||
935 | glBindTexture(GL_TEXTURE_2D, planar->tex[0]); |
||
936 | |||
937 | glActiveTexture(GL_TEXTURE1); |
||
938 | glBindTexture(GL_TEXTURE_2D, planar->tex[1]); |
||
939 | |||
940 | glActiveTexture(GL_TEXTURE2); |
||
941 | glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]); |
||
942 | |||
943 | glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
||
944 | |||
945 | glFlush(); |
||
946 | |||
947 | return; |
||
948 | }; |
||
949 | |||
5371 | serge | 950 | static int hw_create_client(int x, int y, uint32_t width, uint32_t height) |
951 | { |
||
952 | px = create_render(eglGetCurrentDisplay(), eglGetCurrentContext(), x, y, width, height); |
||
953 | |||
954 | return !px; |
||
955 | }; |
||
956 | |||
957 | static int hw_resize_client(int x, int y, uint32_t width, uint32_t height) |
||
958 | { |
||
959 | if( x != px->dx || |
||
960 | y != px->dy || |
||
961 | width != px->width || |
||
962 | height != px->height ) |
||
963 | { |
||
964 | struct drm_i915_mask_update update; |
||
965 | |||
966 | px->dx = x; |
||
967 | px->dy = y; |
||
968 | px->width = width; |
||
969 | px->height = height; |
||
970 | update_mask(px); |
||
971 | |||
972 | update.handle = px->mask.handle; |
||
973 | update.dx = px->dx; |
||
974 | update.dy = px->dy; |
||
975 | update.width = px->width; |
||
976 | update.height = px->height; |
||
977 | update.bo_pitch = (px->width+15) & ~15; |
||
978 | update.bo_map = (int)px->mask.buffer; |
||
979 | update.forced = 1; |
||
980 | |||
981 | drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update); |
||
982 | }; |
||
983 | |||
984 | return 0; |
||
985 | }; |
||
986 | |||
987 | static void hw_fini(void) |
||
988 | { |
||
989 | struct drm_gem_close close; |
||
990 | |||
991 | DBG("%s\n", __FUNCTION__); |
||
992 | |||
993 | eglDestroyImageKHR(px->dpy, px->mask.image); |
||
994 | user_free(px->mask.buffer); |
||
995 | close.handle = px->mask.handle; |
||
996 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
997 | |||
998 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||
999 | glDeleteFramebuffers(1, &px->framebuffer); |
||
1000 | eglDestroyImageKHR(px->dpy, px->screen); |
||
1001 | glDeleteTextures(2, px->texture); |
||
1002 | egl_destroy(px->dpy, px->context); |
||
1003 | free(px); |
||
1004 | }; |
||
1005 | |||
1006 | static struct pix_driver gl_driver = |
||
1007 | { |
||
1008 | HW_TEX_BLIT, |
||
1009 | hw_create_bitmap, |
||
1010 | hw_destroy_bitmap, |
||
1011 | hw_lock_bitmap, |
||
1012 | hw_resize_bitmap, |
||
1013 | hw_blit, |
||
1014 | hw_create_client, |
||
1015 | hw_resize_client, |
||
6115 | serge | 1016 | hw_fini, |
6137 | serge | 1017 | hw_create_planar, |
1018 | hw_blit_planar |
||
5371 | serge | 1019 | }; |
1020 | |||
1021 | struct pix_driver *DrvInit(uint32_t service) |
||
1022 | { |
||
1023 | EGLDisplay dpy; |
||
1024 | EGLConfig config; |
||
1025 | EGLContext context; |
||
1026 | int ret; |
||
1027 | |||
1028 | ret = egl_initialize(&dpy, &config, &context); |
||
1029 | if( ret ) |
||
1030 | return NULL; |
||
1031 | |||
1032 | return &gl_driver; |
||
1033 | |||
1034 | err_0: |
||
1035 | egl_destroy(dpy, context); |
||
1036 | return NULL; |
||
1037 | }> |
||
1038 |