Rev 6137 | Rev 6334 | 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 | |||
6142 | serge | 618 | static int hw_destroy_planar(planar_t *planar) |
619 | { |
||
620 | glDeleteTextures(planar->num_planes, &planar->tex[0]); |
||
621 | |||
622 | if(planar->image[2] != NULL) |
||
623 | eglDestroyImageKHR(px->dpy, planar->image[2]); |
||
624 | if(planar->image[1] != NULL) |
||
625 | eglDestroyImageKHR(px->dpy, planar->image[1]); |
||
626 | if(planar->image[0] != NULL) |
||
627 | eglDestroyImageKHR(px->dpy, planar->image[0]); |
||
628 | if(planar->planar_image != NULL) |
||
629 | eglDestroyImageKHR(px->dpy, planar->planar_image); |
||
630 | free(planar); |
||
631 | return 0; |
||
632 | }; |
||
633 | |||
6115 | serge | 634 | static planar_t* hw_create_planar(EGLint name, EGLint format, uint32_t width, uint32_t height, |
635 | uint32_t offset0, uint32_t pitch0, |
||
636 | uint32_t offset1, uint32_t pitch1, |
||
637 | uint32_t offset2, uint32_t pitch2) |
||
638 | { |
||
639 | struct drm_gem_close close; |
||
640 | planar_t *planar; |
||
641 | EGLImageKHR img; |
||
642 | int num_planes; |
||
643 | int i; |
||
644 | |||
645 | EGLint attribs[] = { |
||
646 | EGL_WIDTH, width, |
||
647 | EGL_HEIGHT,height, |
||
648 | EGL_DRM_BUFFER_FORMAT_MESA, format, |
||
649 | EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset0, |
||
650 | EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch0, |
||
651 | EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset1, |
||
652 | EGL_DMA_BUF_PLANE1_PITCH_EXT, pitch1, |
||
653 | EGL_DMA_BUF_PLANE2_OFFSET_EXT, offset2, |
||
654 | EGL_DMA_BUF_PLANE2_PITCH_EXT, pitch2, |
||
655 | EGL_NONE, EGL_NONE |
||
656 | }; |
||
657 | |||
658 | switch (format) |
||
659 | { |
||
6137 | serge | 660 | case WL_DRM_FORMAT_NV12: |
6115 | serge | 661 | num_planes = 2; |
662 | break; |
||
663 | case EGL_TEXTURE_Y_U_V_WL: |
||
664 | num_planes = 3; |
||
665 | break; |
||
666 | case EGL_TEXTURE_Y_XUXV_WL: |
||
667 | num_planes = 2; |
||
668 | break; |
||
669 | default: |
||
670 | num_planes = 0; |
||
671 | } |
||
672 | |||
6137 | serge | 673 | // printf("%s num_planes %d\n", __FUNCTION__, num_planes); |
674 | |||
6115 | serge | 675 | if(num_planes == 0) |
6137 | serge | 676 | goto fail; |
6115 | serge | 677 | |
678 | planar = calloc(1, sizeof(struct planar)); |
||
679 | if(planar == NULL) |
||
6137 | serge | 680 | goto fail; |
6115 | serge | 681 | |
682 | img = eglCreatePlanarImage(px->dpy, px->context, (EGLClientBuffer)name, attribs); |
||
683 | if(img == NULL) |
||
684 | goto err_0; |
||
685 | |||
686 | planar->width = width; |
||
687 | planar->height = height; |
||
688 | planar->name = name; |
||
6142 | serge | 689 | planar->num_planes = num_planes; |
6115 | serge | 690 | planar->planar_image = img; |
691 | |||
692 | planar->offset[0] = offset0; |
||
693 | planar->offset[1] = offset1; |
||
694 | planar->offset[2] = offset2; |
||
695 | |||
696 | planar->pitch[0] = pitch0; |
||
697 | planar->pitch[1] = pitch1; |
||
698 | planar->pitch[2] = pitch2; |
||
699 | |||
700 | glGenTextures(num_planes, &planar->tex[0]); |
||
6142 | serge | 701 | if(glGetError() != GL_NO_ERROR) |
702 | goto err_0; |
||
6115 | serge | 703 | |
704 | for(i = 0; i < num_planes; i++) |
||
705 | { |
||
6137 | serge | 706 | EGLImageKHR image; |
6115 | serge | 707 | EGLint attr[3]; |
708 | attr[0] = EGL_WAYLAND_PLANE_WL; |
||
709 | attr[1] = i; |
||
710 | attr[2] = EGL_NONE; |
||
711 | |||
6137 | serge | 712 | image = eglCreateImageKHR(px->dpy, px->context, |
713 | EGL_WAYLAND_BUFFER_WL,(EGLClientBuffer)img, attr); |
||
6142 | serge | 714 | if(image == NULL) |
715 | goto err_1; |
||
6115 | serge | 716 | |
6137 | serge | 717 | planar->image[i] = image; |
6115 | serge | 718 | glBindTexture(GL_TEXTURE_2D, planar->tex[i]); |
6137 | serge | 719 | if(glGetError() != GL_NO_ERROR) |
720 | { |
||
6142 | serge | 721 | goto err_1; |
6137 | serge | 722 | }; |
6115 | serge | 723 | |
6137 | serge | 724 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); |
725 | if(glGetError() != GL_NO_ERROR) |
||
726 | { |
||
6142 | serge | 727 | goto err_1; |
6137 | serge | 728 | } |
729 | |||
6115 | serge | 730 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); |
731 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); |
||
732 | }; |
||
733 | |||
734 | return planar; |
||
735 | |||
6142 | serge | 736 | err_1: |
737 | hw_destroy_planar(planar); |
||
738 | return NULL; |
||
739 | |||
6115 | serge | 740 | err_0: |
741 | free(planar); |
||
6137 | serge | 742 | fail: |
6115 | serge | 743 | return NULL; |
744 | } |
||
745 | |||
5371 | serge | 746 | static int hw_destroy_bitmap(bitmap_t * bitmap) |
747 | { |
||
748 | struct drm_gem_close close; |
||
749 | |||
750 | glDeleteTextures(1, &bitmap->tex); |
||
751 | eglDestroyImageKHR(px->dpy, bitmap->image); |
||
752 | user_free(bitmap->buffer); |
||
753 | close.handle = bitmap->handle; |
||
754 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
755 | free(bitmap); |
||
6142 | serge | 756 | return 0; |
5371 | serge | 757 | }; |
758 | |||
759 | static void *hw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch) |
||
760 | { |
||
761 | *pitch = bitmap->pitch; |
||
762 | |||
763 | return bitmap->buffer; |
||
764 | }; |
||
765 | |||
766 | static int hw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height) |
||
767 | { |
||
768 | return 0; |
||
769 | } |
||
770 | |||
771 | char proc_info[1024]; |
||
772 | |||
773 | static int hw_blit(bitmap_t *bitmap, int dst_x, int dst_y, |
||
774 | uint32_t w, uint32_t h, int src_x, int src_y) |
||
775 | { |
||
776 | struct drm_i915_mask_update update; |
||
777 | struct drm_i915_fb_info fb; |
||
778 | |||
779 | uint32_t winx, winy, winw, winh; |
||
780 | uint8_t state; |
||
781 | float xscale, yscale; |
||
782 | int r, b; |
||
783 | float *vertices = px->vertices; |
||
784 | |||
785 | get_proc_info(proc_info); |
||
786 | |||
787 | state = *(uint8_t*)(proc_info+70); |
||
788 | if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED)) |
||
789 | return; |
||
790 | |||
791 | winx = *(uint32_t*)(proc_info+34); |
||
792 | winy = *(uint32_t*)(proc_info+38); |
||
793 | winw = *(uint32_t*)(proc_info+42)+1; |
||
794 | winh = *(uint32_t*)(proc_info+46)+1; |
||
795 | |||
796 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
797 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
798 | { |
||
799 | DBG("failed to get framebuffer info\n"); |
||
800 | return; |
||
801 | }; |
||
802 | |||
803 | if( fb.width != px->scr_width || |
||
804 | fb.height != px->scr_height ) |
||
805 | { |
||
806 | px->scr_width = fb.width; |
||
807 | px->scr_height = fb.height; |
||
808 | |||
809 | eglDestroyImageKHR(px->dpy, px->screen); |
||
810 | |||
811 | if(update_fb(px, fb.name, fb.pitch)) |
||
812 | return; |
||
813 | }; |
||
814 | |||
815 | update.handle = px->mask.handle; |
||
816 | update.dx = px->dx; |
||
817 | update.dy = px->dy; |
||
818 | update.width = px->width; |
||
819 | update.height = px->height; |
||
820 | update.bo_pitch = (px->width+15) & ~15; |
||
821 | update.bo_map = (int)px->mask.buffer; |
||
822 | |||
823 | if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update)) |
||
824 | { |
||
825 | return; |
||
826 | } |
||
827 | |||
828 | xscale = 1.0/px->scr_width; |
||
829 | yscale = 1.0/px->scr_height; |
||
830 | |||
831 | r = winx + px->dx + px->width; |
||
832 | b = winy + px->dy + px->height; |
||
833 | |||
834 | float t0, t1, t2, t5; |
||
835 | |||
836 | // render->tc_src[1*2] = 1.0; |
||
837 | // render->tc_src[2*2] = 1.0; |
||
838 | // render->tc_src[2*2+1]= 1.0; |
||
839 | // render->tc_src[3*2+1]= 1.0; |
||
840 | |||
841 | vertices[0] = t0 = 2*(winx+px->dx)*xscale - 1.0; |
||
842 | vertices[1 * 2] = t2 = 2*r*xscale - 1.0; |
||
843 | |||
844 | vertices[2 * 2] = t2; |
||
845 | vertices[3 * 2] = t0; |
||
846 | |||
847 | vertices[1] = t1 = 2*(winy+px->dy)*yscale - 1.0; |
||
848 | vertices[2*2+1] = t5 = 2*b*yscale - 1.0; |
||
849 | vertices[1*2+1] = t1; |
||
850 | vertices[3*2+1] = t5; |
||
851 | |||
6137 | serge | 852 | struct shader *shader = &px->shader_rgba; |
853 | |||
854 | glUseProgram(shader->blit_prog); |
||
855 | glUniform1i(shader->sampler0, 0); |
||
856 | glUniform1i(shader->sm_mask, 1); |
||
857 | |||
5371 | serge | 858 | glActiveTexture(GL_TEXTURE0); |
859 | glBindTexture(GL_TEXTURE_2D, bitmap->tex); |
||
860 | |||
861 | glActiveTexture(GL_TEXTURE1); |
||
862 | glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]); |
||
863 | |||
864 | glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
||
865 | |||
866 | glFlush(); |
||
867 | |||
868 | return; |
||
869 | }; |
||
870 | |||
6137 | serge | 871 | static int hw_blit_planar(planar_t *planar, int dst_x, int dst_y, |
872 | uint32_t w, uint32_t h, int src_x, int src_y) |
||
873 | { |
||
874 | struct drm_i915_mask_update update; |
||
875 | struct drm_i915_fb_info fb; |
||
876 | |||
877 | uint32_t winx, winy, winw, winh; |
||
878 | uint8_t state; |
||
879 | float xscale, yscale; |
||
880 | int r, b; |
||
881 | float *vertices = px->vertices; |
||
882 | |||
883 | get_proc_info(proc_info); |
||
884 | |||
885 | state = *(uint8_t*)(proc_info+70); |
||
886 | if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED)) |
||
887 | return; |
||
888 | |||
889 | winx = *(uint32_t*)(proc_info+34); |
||
890 | winy = *(uint32_t*)(proc_info+38); |
||
891 | winw = *(uint32_t*)(proc_info+42)+1; |
||
892 | winh = *(uint32_t*)(proc_info+46)+1; |
||
893 | |||
894 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
895 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
896 | { |
||
897 | DBG("failed to get framebuffer info\n"); |
||
898 | return; |
||
899 | }; |
||
900 | |||
901 | if( fb.width != px->scr_width || |
||
902 | fb.height != px->scr_height ) |
||
903 | { |
||
904 | px->scr_width = fb.width; |
||
905 | px->scr_height = fb.height; |
||
906 | |||
907 | eglDestroyImageKHR(px->dpy, px->screen); |
||
908 | |||
909 | if(update_fb(px, fb.name, fb.pitch)) |
||
910 | return; |
||
911 | }; |
||
912 | |||
913 | update.handle = px->mask.handle; |
||
914 | update.dx = px->dx; |
||
915 | update.dy = px->dy; |
||
916 | update.width = px->width; |
||
917 | update.height = px->height; |
||
918 | update.bo_pitch = (px->width+15) & ~15; |
||
919 | update.bo_map = (int)px->mask.buffer; |
||
920 | |||
921 | if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update)) |
||
922 | { |
||
923 | return; |
||
924 | } |
||
925 | |||
926 | xscale = 1.0/px->scr_width; |
||
927 | yscale = 1.0/px->scr_height; |
||
928 | |||
929 | r = winx + px->dx + px->width; |
||
930 | b = winy + px->dy + px->height; |
||
931 | |||
932 | float t0, t1, t2, t5; |
||
933 | |||
934 | // render->tc_src[1*2] = 1.0; |
||
935 | // render->tc_src[2*2] = 1.0; |
||
936 | // render->tc_src[2*2+1]= 1.0; |
||
937 | // render->tc_src[3*2+1]= 1.0; |
||
938 | |||
939 | vertices[0] = t0 = 2*(winx+px->dx)*xscale - 1.0; |
||
940 | vertices[1 * 2] = t2 = 2*r*xscale - 1.0; |
||
941 | |||
942 | vertices[2 * 2] = t2; |
||
943 | vertices[3 * 2] = t0; |
||
944 | |||
945 | vertices[1] = t1 = 2*(winy+px->dy)*yscale - 1.0; |
||
946 | vertices[2*2+1] = t5 = 2*b*yscale - 1.0; |
||
947 | vertices[1*2+1] = t1; |
||
948 | vertices[3*2+1] = t5; |
||
949 | |||
950 | struct shader *shader = &px->shader_y_uv; |
||
951 | |||
952 | glUseProgram(shader->blit_prog); |
||
953 | glUniform1i(shader->sampler0, 0); |
||
954 | glUniform1i(shader->sampler1, 1); |
||
955 | glUniform1i(shader->sm_mask, 2); |
||
956 | |||
957 | glActiveTexture(GL_TEXTURE0); |
||
958 | glBindTexture(GL_TEXTURE_2D, planar->tex[0]); |
||
959 | |||
960 | glActiveTexture(GL_TEXTURE1); |
||
961 | glBindTexture(GL_TEXTURE_2D, planar->tex[1]); |
||
962 | |||
963 | glActiveTexture(GL_TEXTURE2); |
||
964 | glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]); |
||
965 | |||
966 | glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
||
967 | |||
968 | glFlush(); |
||
969 | |||
970 | return; |
||
971 | }; |
||
972 | |||
5371 | serge | 973 | static int hw_create_client(int x, int y, uint32_t width, uint32_t height) |
974 | { |
||
975 | px = create_render(eglGetCurrentDisplay(), eglGetCurrentContext(), x, y, width, height); |
||
976 | |||
977 | return !px; |
||
978 | }; |
||
979 | |||
980 | static int hw_resize_client(int x, int y, uint32_t width, uint32_t height) |
||
981 | { |
||
982 | if( x != px->dx || |
||
983 | y != px->dy || |
||
984 | width != px->width || |
||
985 | height != px->height ) |
||
986 | { |
||
987 | struct drm_i915_mask_update update; |
||
988 | |||
989 | px->dx = x; |
||
990 | px->dy = y; |
||
991 | px->width = width; |
||
992 | px->height = height; |
||
993 | update_mask(px); |
||
994 | |||
995 | update.handle = px->mask.handle; |
||
996 | update.dx = px->dx; |
||
997 | update.dy = px->dy; |
||
998 | update.width = px->width; |
||
999 | update.height = px->height; |
||
1000 | update.bo_pitch = (px->width+15) & ~15; |
||
1001 | update.bo_map = (int)px->mask.buffer; |
||
1002 | update.forced = 1; |
||
1003 | |||
1004 | drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update); |
||
1005 | }; |
||
1006 | |||
1007 | return 0; |
||
1008 | }; |
||
1009 | |||
1010 | static void hw_fini(void) |
||
1011 | { |
||
1012 | struct drm_gem_close close; |
||
1013 | |||
1014 | DBG("%s\n", __FUNCTION__); |
||
1015 | |||
1016 | eglDestroyImageKHR(px->dpy, px->mask.image); |
||
1017 | user_free(px->mask.buffer); |
||
1018 | close.handle = px->mask.handle; |
||
1019 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
1020 | |||
1021 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||
1022 | glDeleteFramebuffers(1, &px->framebuffer); |
||
1023 | eglDestroyImageKHR(px->dpy, px->screen); |
||
1024 | glDeleteTextures(2, px->texture); |
||
1025 | egl_destroy(px->dpy, px->context); |
||
1026 | free(px); |
||
1027 | }; |
||
1028 | |||
1029 | static struct pix_driver gl_driver = |
||
1030 | { |
||
1031 | HW_TEX_BLIT, |
||
1032 | hw_create_bitmap, |
||
1033 | hw_destroy_bitmap, |
||
1034 | hw_lock_bitmap, |
||
1035 | hw_resize_bitmap, |
||
1036 | hw_blit, |
||
1037 | hw_create_client, |
||
1038 | hw_resize_client, |
||
6115 | serge | 1039 | hw_fini, |
6137 | serge | 1040 | hw_create_planar, |
6142 | serge | 1041 | hw_destroy_planar, |
6137 | serge | 1042 | hw_blit_planar |
5371 | serge | 1043 | }; |
1044 | |||
1045 | struct pix_driver *DrvInit(uint32_t service) |
||
1046 | { |
||
1047 | EGLDisplay dpy; |
||
1048 | EGLConfig config; |
||
1049 | EGLContext context; |
||
1050 | int ret; |
||
1051 | |||
1052 | ret = egl_initialize(&dpy, &config, &context); |
||
1053 | if( ret ) |
||
1054 | return NULL; |
||
1055 | |||
1056 | return &gl_driver; |
||
1057 | |||
1058 | err_0: |
||
1059 | egl_destroy(dpy, context); |
||
1060 | return NULL; |
||
1061 | }> |
||
1062 |