Rev 5602 | Rev 6137 | 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 | |||
13 | static int drm_ioctl(int fd, unsigned long request, void *arg) |
||
14 | { |
||
15 | ioctl_t io; |
||
16 | |||
17 | io.handle = fd; |
||
18 | io.io_code = request; |
||
19 | io.input = arg; |
||
20 | io.inp_size = 64; |
||
21 | io.output = NULL; |
||
22 | io.out_size = 0; |
||
23 | |||
24 | return call_service(&io); |
||
25 | } |
||
26 | |||
27 | static EGLImageKHR px_create_image(struct render *px,void *name,GLuint tex, EGLint *attribs) |
||
28 | { |
||
29 | EGLImageKHR image; |
||
30 | |||
31 | image = eglCreateImageKHR(px->dpy, px->context, |
||
32 | EGL_DRM_BUFFER_MESA, name, attribs); |
||
33 | if(image == NULL) |
||
34 | goto err_0; |
||
35 | |||
36 | glBindTexture(GL_TEXTURE_2D, tex); |
||
37 | if(glGetError() != GL_NO_ERROR) |
||
38 | goto err_1; |
||
39 | |||
40 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); |
||
41 | if(glGetError() != GL_NO_ERROR) |
||
42 | goto err_1; |
||
43 | |||
5602 | serge | 44 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); |
45 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); |
||
5371 | serge | 46 | |
47 | return image; |
||
48 | |||
49 | err_1: |
||
50 | eglDestroyImageKHR(px->dpy, image); |
||
51 | err_0: |
||
52 | return NULL; |
||
53 | }; |
||
54 | |||
55 | static int update_fb(struct render *px, int name, int pitch) |
||
56 | { |
||
57 | GLenum status; |
||
58 | EGLImageKHR screen; |
||
59 | |||
60 | EGLint attribs[] = { |
||
61 | EGL_WIDTH, px->scr_width, |
||
62 | EGL_HEIGHT, px->scr_height, |
||
63 | EGL_DRM_BUFFER_STRIDE_MESA, pitch/4, |
||
64 | EGL_DRM_BUFFER_FORMAT_MESA, |
||
65 | EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, |
||
66 | EGL_DRM_BUFFER_USE_MESA, |
||
67 | EGL_DRM_BUFFER_USE_SHARE_MESA | |
||
68 | EGL_DRM_BUFFER_USE_SCANOUT_MESA, |
||
69 | EGL_NONE |
||
70 | }; |
||
71 | char *errmsg; |
||
72 | |||
73 | px->screen = px_create_image(px,(void*)name, px->texture[TEX_SCREEN], attribs); |
||
74 | errmsg = "failed to create new screen image\n"; |
||
75 | if(px->screen == EGL_NO_IMAGE_KHR) |
||
76 | goto err_0; |
||
77 | |||
78 | px->screen = screen; |
||
79 | |||
80 | glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, |
||
81 | GL_TEXTURE_2D, px->texture[TEX_SCREEN],0); |
||
82 | |||
83 | status = glCheckFramebufferStatus(GL_FRAMEBUFFER); |
||
84 | if (status != GL_FRAMEBUFFER_COMPLETE) |
||
85 | { |
||
86 | const char *str; |
||
87 | switch (status) |
||
88 | { |
||
89 | case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: |
||
90 | str = "incomplete attachment"; |
||
91 | break; |
||
92 | case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: |
||
93 | str = "incomplete/missing attachment"; |
||
94 | break; |
||
95 | case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: |
||
96 | str = "incomplete draw buffer"; |
||
97 | break; |
||
98 | case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: |
||
99 | str = "incomplete read buffer"; |
||
100 | break; |
||
101 | case GL_FRAMEBUFFER_UNSUPPORTED: |
||
102 | str = "unsupported"; |
||
103 | break; |
||
104 | case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: |
||
105 | str = "incomplete multiple"; |
||
106 | break; |
||
107 | default: |
||
108 | str = "unknown error"; |
||
109 | break; |
||
110 | } |
||
111 | DBG("destination framebuffer incomplete: %s [%#x]\n", str, status); |
||
112 | |||
113 | return -1; |
||
114 | }; |
||
115 | |||
116 | DBG("framebuffer changed successfull\n"); |
||
117 | |||
118 | glViewport(0, 0, px->scr_width, px->scr_height); |
||
119 | |||
120 | return 0; |
||
121 | |||
122 | err_0: |
||
123 | DBG("%s %s\n", __FUNCTION__, errmsg); |
||
124 | |||
125 | return -1; |
||
126 | }; |
||
127 | |||
128 | static GLint create_shader(GLenum type, const char *source) |
||
129 | { |
||
130 | GLint ok; |
||
131 | GLint shader; |
||
132 | |||
133 | shader = glCreateShader(type); |
||
134 | if(shader == 0) |
||
135 | goto err; |
||
136 | |||
137 | glShaderSource(shader, 1, (const GLchar **) &source, NULL); |
||
138 | glCompileShader(shader); |
||
139 | glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); |
||
140 | if (!ok) { |
||
141 | GLchar *info; |
||
142 | GLint size; |
||
143 | |||
144 | glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); |
||
145 | info = malloc(size); |
||
146 | |||
147 | glGetShaderInfoLog(shader, size, NULL, info); |
||
148 | DBG("Failed to compile %s: %s\n", |
||
149 | type == GL_FRAGMENT_SHADER ? "FS" : "VS",info); |
||
150 | DBG("Program source:\n%s", source); |
||
151 | DBG("GLSL compile failure\n"); |
||
152 | free(info); |
||
153 | glDeleteShader(shader); |
||
154 | shader = 0; |
||
155 | }; |
||
156 | |||
157 | DBG("create shader %d\n", shader); |
||
158 | err: |
||
159 | return shader; |
||
160 | } |
||
161 | |||
162 | |||
163 | static void *px_create_obj(struct render *px, size_t size, |
||
164 | GLuint *handle, GLuint *name) |
||
165 | { |
||
166 | struct drm_i915_gem_create create; |
||
167 | struct drm_i915_gem_mmap mmap_arg; |
||
168 | struct drm_gem_close close; |
||
169 | struct drm_gem_flink flink; |
||
170 | |||
171 | create.size = size; |
||
172 | create.handle = 0; |
||
173 | |||
174 | if(drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_CREATE, &create)) |
||
175 | goto err_0; |
||
176 | |||
177 | *handle = create.handle; |
||
178 | flink.handle = create.handle; |
||
179 | if (drm_ioctl(px->fd, DRM_IOCTL_GEM_FLINK, &flink)) |
||
180 | goto err_1; |
||
181 | |||
182 | *name = flink.name; |
||
183 | |||
184 | mmap_arg.handle = *handle; |
||
185 | mmap_arg.offset = 0; |
||
186 | mmap_arg.size = size; |
||
187 | if (drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg)) |
||
188 | { |
||
189 | DBG("%s: failed to mmap bitmap handle=%d, %d bytes, into CPU domain\n", |
||
190 | __FUNCTION__, *handle, size); |
||
191 | goto err_1; |
||
192 | }; |
||
193 | |||
194 | return (void*)(uintptr_t)mmap_arg.addr_ptr; |
||
195 | |||
196 | err_1: |
||
197 | close.handle = *handle; |
||
198 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
199 | err_0: |
||
200 | return NULL; |
||
201 | }; |
||
202 | |||
203 | static int px_create_bitmap(struct render *px, struct bitmap *bitmap, |
||
204 | size_t size, EGLint format) |
||
205 | { |
||
206 | struct drm_gem_close close; |
||
207 | EGLint attribs[] = { |
||
208 | EGL_WIDTH, bitmap->width, |
||
209 | EGL_HEIGHT, bitmap->height, |
||
210 | EGL_DRM_BUFFER_STRIDE_MESA, 0, |
||
211 | EGL_DRM_BUFFER_FORMAT_MESA, |
||
212 | format, |
||
213 | EGL_DRM_BUFFER_USE_MESA, |
||
214 | EGL_DRM_BUFFER_USE_SHARE_MESA, |
||
215 | EGL_NONE |
||
216 | }; |
||
217 | |||
218 | bitmap->buffer = px_create_obj(px, size, &bitmap->handle, &bitmap->name); |
||
219 | if(bitmap->buffer == NULL) |
||
220 | goto err_0; |
||
221 | |||
222 | switch(format) |
||
223 | { |
||
224 | case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: |
||
225 | attribs[5] = bitmap->pitch/4; |
||
226 | break; |
||
227 | case EGL_DRM_BUFFER_FORMAT_R8_MESA: |
||
228 | attribs[5] = bitmap->pitch; |
||
229 | break; |
||
230 | default: |
||
231 | DBG("%s invalid format %x\n", |
||
232 | __FUNCTION__, format); |
||
233 | goto err_1; |
||
234 | } |
||
235 | |||
236 | bitmap->image = px_create_image(px,(void*)bitmap->name, |
||
237 | bitmap->tex, attribs); |
||
238 | if(bitmap->image == NULL) |
||
239 | goto err_1; |
||
240 | |||
241 | DBG("create bitmap:%p %dx%d pitch:%d\n" |
||
242 | "KHRimage:%p gl_tex:%d handle:%d name:%d\n" |
||
243 | "mapped at %x\n", |
||
244 | bitmap, bitmap->width, bitmap->height, bitmap->pitch, |
||
245 | bitmap->image, bitmap->tex, bitmap->handle, bitmap->name, |
||
246 | bitmap->buffer); |
||
247 | |||
248 | return 0; |
||
249 | |||
250 | err_1: |
||
251 | user_free(bitmap->buffer); |
||
252 | close.handle = bitmap->handle; |
||
253 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
254 | err_0: |
||
255 | return -1; |
||
256 | } |
||
257 | |||
258 | |||
259 | static int create_mask(struct render *px) |
||
260 | { |
||
261 | struct drm_i915_mask_update update; |
||
262 | int pitch; |
||
263 | |||
264 | pitch = (px->width+15) & ~15; |
||
265 | |||
266 | px->mask.width = px->width; |
||
267 | px->mask.height = px->height; |
||
268 | px->mask.pitch = pitch; |
||
269 | px->mask.tex = px->texture[TEX_MASK]; |
||
270 | px->mask_size = pitch * px->height; |
||
271 | |||
272 | if(px_create_bitmap(px, &px->mask, px->mask_size, |
||
273 | EGL_DRM_BUFFER_FORMAT_R8_MESA) == 0) |
||
274 | { |
||
275 | update.handle = px->mask.handle; |
||
276 | update.dx = px->dx; |
||
277 | update.dy = px->dy; |
||
278 | update.width = px->width; |
||
279 | update.height = px->height; |
||
280 | update.bo_pitch = (px->width+15) & ~15; |
||
281 | update.bo_map = (int)px->mask.buffer; |
||
282 | update.forced = 1; |
||
283 | drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update); |
||
284 | return 0; |
||
285 | }; |
||
286 | return -1; |
||
287 | }; |
||
288 | |||
289 | |||
290 | static int update_mask(struct render *px) |
||
291 | { |
||
292 | struct drm_gem_close close; |
||
293 | EGLint attribs[] = { |
||
294 | EGL_WIDTH, 0, |
||
295 | EGL_HEIGHT, 0, |
||
296 | EGL_DRM_BUFFER_STRIDE_MESA, 0, |
||
297 | EGL_DRM_BUFFER_FORMAT_MESA, |
||
298 | EGL_DRM_BUFFER_FORMAT_R8_MESA, |
||
299 | EGL_DRM_BUFFER_USE_MESA, |
||
300 | EGL_DRM_BUFFER_USE_SHARE_MESA, |
||
301 | EGL_NONE |
||
302 | }; |
||
303 | unsigned int size, pitch; |
||
304 | |||
305 | eglDestroyImageKHR(px->dpy, px->mask.image); |
||
306 | |||
307 | pitch = (px->width+15) & ~15; |
||
308 | size = pitch*px->height; |
||
309 | |||
310 | if(size > px->mask_size) |
||
311 | { |
||
312 | user_free(px->mask.buffer); |
||
313 | close.handle = px->mask.handle; |
||
314 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
315 | |||
316 | px->mask_size = size; |
||
317 | |||
318 | px->mask.buffer = px_create_obj(px, px->mask_size, |
||
319 | &px->mask.handle, &px->mask.name); |
||
320 | if(px->mask.buffer == 0) |
||
321 | goto err_0; |
||
322 | }; |
||
323 | |||
324 | attribs[1] = px->width; |
||
325 | attribs[3] = px->height; |
||
326 | attribs[5] = pitch; |
||
327 | |||
328 | px->mask.image = px_create_image(px,(void*)px->mask.name, |
||
329 | px->mask.tex, attribs); |
||
330 | if(px->mask.image == NULL) |
||
331 | goto err_1; |
||
332 | |||
333 | DBG("create mask w:%d h:%d pitch:%d\n" |
||
334 | "KHRimage:%p gl_tex:%d handle:%d name:%d\n" |
||
335 | "mapped at %x\n", |
||
336 | px->width, px->height, |
||
337 | pitch, px->mask.image, px->texture[TEX_MASK], |
||
338 | px->mask.handle, px->mask.name, px->mask.buffer); |
||
339 | |||
340 | return 0; |
||
341 | |||
342 | err_1: |
||
343 | user_free(px->mask.buffer); |
||
344 | close.handle = px->mask.handle; |
||
345 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
346 | err_0: |
||
347 | return -1; |
||
348 | }; |
||
349 | |||
350 | static struct render* create_render(EGLDisplay dpy, EGLContext context, int dx, int dy, int w, int h) |
||
351 | { |
||
352 | const char *vs_src = |
||
353 | "attribute vec4 v_position;\n" |
||
354 | "attribute vec4 v_texcoord0;\n" |
||
355 | "varying vec2 source_texture;\n" |
||
356 | "void main()\n" |
||
357 | "{\n" |
||
358 | " gl_Position = v_position;\n" |
||
359 | " source_texture = v_texcoord0.xy;\n" |
||
360 | "}\n"; |
||
361 | |||
362 | const char *fs_i965 = |
||
363 | "varying vec2 source_texture;\n" |
||
364 | "uniform sampler2D sampler_src;\n" |
||
365 | "uniform sampler2D sampler_mask;\n" |
||
366 | "void main()\n" |
||
367 | "{\n" |
||
368 | " float ca = texture2D(sampler_mask, source_texture).r;\n" |
||
369 | " gl_FragColor = vec4(texture2D(sampler_src, source_texture).rgb, ca);\n" |
||
370 | "}\n"; |
||
371 | |||
372 | struct drm_i915_fb_info fb; |
||
373 | struct render *px; |
||
374 | GLint vs_shader, fs_shader; |
||
375 | int ret; |
||
376 | |||
377 | px = (struct render*)malloc(sizeof(struct render)); |
||
378 | if(px == NULL) |
||
379 | goto err_0; |
||
380 | |||
381 | px->fd = get_service("DISPLAY"); |
||
382 | |||
383 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
384 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
385 | { DBG("failed to get framebuffer info\n"); |
||
386 | goto err_1; |
||
387 | }; |
||
388 | |||
389 | px->dpy = dpy; |
||
390 | px->context = context; |
||
391 | px->dx = dx; |
||
392 | px->dy = dy; |
||
393 | px->width = w; |
||
394 | px->height = h; |
||
395 | px->scr_width = fb.width; |
||
396 | px->scr_height = fb.height; |
||
397 | |||
398 | glGenTextures(2, px->texture); |
||
399 | if(glGetError() != GL_NO_ERROR) |
||
400 | goto err_1; |
||
401 | |||
402 | glGenFramebuffers(1, &px->framebuffer); |
||
403 | if(glGetError() != GL_NO_ERROR) |
||
404 | goto err_2; |
||
405 | |||
406 | glBindFramebuffer(GL_FRAMEBUFFER, px->framebuffer); |
||
407 | if(glGetError() != GL_NO_ERROR) |
||
408 | goto err_3; |
||
409 | |||
410 | if(update_fb(px, fb.name, fb.pitch)) |
||
411 | goto err_4; |
||
412 | |||
413 | glMatrixMode(GL_PROJECTION); |
||
414 | glLoadIdentity(); |
||
415 | glMatrixMode(GL_MODELVIEW); |
||
416 | glLoadIdentity(); |
||
417 | |||
418 | if(create_mask(px)) |
||
419 | goto err_4; |
||
420 | |||
421 | px->blit_prog = glCreateProgram(); |
||
422 | if(px->blit_prog == 0) |
||
423 | goto err_4; |
||
424 | |||
425 | vs_shader = create_shader(GL_VERTEX_SHADER, vs_src); |
||
426 | if(vs_shader == 0) |
||
427 | goto err_4; |
||
428 | |||
429 | fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_i965); |
||
430 | if(fs_shader == 0) |
||
431 | goto err_4; |
||
432 | |||
433 | glAttachShader(px->blit_prog, vs_shader); |
||
434 | glAttachShader(px->blit_prog, fs_shader); |
||
435 | glBindAttribLocation(px->blit_prog, 0, "v_position"); |
||
436 | glBindAttribLocation(px->blit_prog, 1, "v_texcoord0"); |
||
437 | |||
438 | glLinkProgram(px->blit_prog); |
||
439 | glGetProgramiv(px->blit_prog, GL_LINK_STATUS, &ret); |
||
440 | if (!ret) |
||
441 | { |
||
442 | GLchar *info; |
||
443 | GLint size; |
||
444 | |||
445 | glGetProgramiv(px->blit_prog, GL_INFO_LOG_LENGTH, &size); |
||
446 | info = malloc(size); |
||
447 | |||
448 | glGetProgramInfoLog(px->blit_prog, size, NULL, info); |
||
449 | DBG("Failed to link: %s\n", info); |
||
450 | DBG("GLSL link failure\n"); |
||
451 | free(info); |
||
452 | goto err_4; |
||
453 | } |
||
454 | |||
455 | px->sampler = glGetUniformLocation(px->blit_prog,"sampler_src"); |
||
456 | px->sm_mask = glGetUniformLocation(px->blit_prog,"sampler_mask"); |
||
457 | |||
458 | glUseProgram(px->blit_prog); |
||
459 | glUniform1i(px->sampler, 0); |
||
460 | glUniform1i(px->sm_mask, 1); |
||
461 | |||
462 | glEnableClientState(GL_VERTEX_ARRAY); |
||
463 | |||
464 | glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->vertices); |
||
465 | glEnableVertexAttribArray(0); |
||
466 | |||
467 | glVertexAttribPointer(1, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->tc_src); |
||
468 | glEnableVertexAttribArray(1); |
||
469 | |||
470 | glEnable(GL_BLEND); |
||
471 | glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); |
||
472 | |||
473 | px->tc_src[0] = 0.0; |
||
474 | px->tc_src[1] = 0.0; |
||
475 | px->tc_src[1*2] = 1.0; |
||
476 | px->tc_src[1*2+1]= 0.0; |
||
477 | px->tc_src[2*2] = 1.0; |
||
478 | px->tc_src[2*2+1]= 1.0; |
||
479 | px->tc_src[3*2] = 0.0; |
||
480 | px->tc_src[3*2+1]= 1.0; |
||
481 | |||
482 | DBG("create render framebuffer:%p %dx%d pitch:%d name %d\n", |
||
483 | px->screen,fb.width, fb.height, fb.pitch, fb.name); |
||
484 | |||
485 | return px; |
||
486 | |||
487 | err_4: |
||
488 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||
489 | err_3: |
||
490 | glDeleteFramebuffers(1, &px->framebuffer); |
||
491 | err_2: |
||
492 | glDeleteTextures(2, px->texture); |
||
493 | err_1: |
||
494 | free(px); |
||
495 | err_0: |
||
496 | return NULL; |
||
497 | }; |
||
498 | |||
499 | static struct render *px; |
||
500 | |||
501 | static bitmap_t *hw_create_bitmap(uint32_t width, uint32_t height) |
||
502 | { |
||
503 | struct bitmap *bitmap; |
||
504 | |||
505 | bitmap = malloc(sizeof(struct bitmap)); |
||
506 | if(bitmap == NULL) |
||
507 | return NULL; |
||
508 | |||
509 | glGenTextures(1, &bitmap->tex); |
||
510 | if(glGetError() != GL_NO_ERROR) |
||
511 | goto err_0; |
||
512 | |||
513 | bitmap->width = width; |
||
514 | bitmap->height = height; |
||
515 | bitmap->pitch = (width*4 + 15) & ~15; |
||
516 | |||
517 | if(px_create_bitmap(px, bitmap, bitmap->pitch * bitmap->height, |
||
518 | EGL_DRM_BUFFER_FORMAT_ARGB32_MESA) == 0) |
||
519 | { |
||
520 | return bitmap; |
||
521 | }; |
||
522 | |||
523 | glDeleteTextures(1, &bitmap->tex); |
||
524 | err_0: |
||
525 | free(bitmap); |
||
526 | return NULL; |
||
527 | }; |
||
528 | |||
6115 | serge | 529 | static planar_t* hw_create_planar(EGLint name, EGLint format, uint32_t width, uint32_t height, |
530 | uint32_t offset0, uint32_t pitch0, |
||
531 | uint32_t offset1, uint32_t pitch1, |
||
532 | uint32_t offset2, uint32_t pitch2) |
||
533 | { |
||
534 | struct drm_gem_close close; |
||
535 | planar_t *planar; |
||
536 | EGLImageKHR img; |
||
537 | int num_planes; |
||
538 | int i; |
||
539 | |||
540 | EGLint attribs[] = { |
||
541 | EGL_WIDTH, width, |
||
542 | EGL_HEIGHT,height, |
||
543 | EGL_DRM_BUFFER_FORMAT_MESA, format, |
||
544 | EGL_DMA_BUF_PLANE0_OFFSET_EXT, offset0, |
||
545 | EGL_DMA_BUF_PLANE0_PITCH_EXT, pitch0, |
||
546 | EGL_DMA_BUF_PLANE1_OFFSET_EXT, offset1, |
||
547 | EGL_DMA_BUF_PLANE1_PITCH_EXT, pitch1, |
||
548 | EGL_DMA_BUF_PLANE2_OFFSET_EXT, offset2, |
||
549 | EGL_DMA_BUF_PLANE2_PITCH_EXT, pitch2, |
||
550 | EGL_NONE, EGL_NONE |
||
551 | }; |
||
552 | |||
553 | switch (format) |
||
554 | { |
||
555 | case EGL_TEXTURE_Y_UV_WL: |
||
556 | num_planes = 2; |
||
557 | break; |
||
558 | case EGL_TEXTURE_Y_U_V_WL: |
||
559 | num_planes = 3; |
||
560 | break; |
||
561 | case EGL_TEXTURE_Y_XUXV_WL: |
||
562 | num_planes = 2; |
||
563 | break; |
||
564 | default: |
||
565 | num_planes = 0; |
||
566 | } |
||
567 | |||
568 | if(num_planes == 0) |
||
569 | return NULL; |
||
570 | |||
571 | planar = calloc(1, sizeof(struct planar)); |
||
572 | if(planar == NULL) |
||
573 | return NULL; |
||
574 | |||
575 | img = eglCreatePlanarImage(px->dpy, px->context, (EGLClientBuffer)name, attribs); |
||
576 | if(img == NULL) |
||
577 | goto err_0; |
||
578 | |||
579 | planar->width = width; |
||
580 | planar->height = height; |
||
581 | planar->name = name; |
||
582 | planar->planar_image = img; |
||
583 | |||
584 | planar->offset[0] = offset0; |
||
585 | planar->offset[1] = offset1; |
||
586 | planar->offset[2] = offset2; |
||
587 | |||
588 | planar->pitch[0] = pitch0; |
||
589 | planar->pitch[1] = pitch1; |
||
590 | planar->pitch[2] = pitch2; |
||
591 | |||
592 | glGenTextures(num_planes, &planar->tex[0]); |
||
593 | |||
594 | for(i = 0; i < num_planes; i++) |
||
595 | { |
||
596 | EGLint attr[3]; |
||
597 | attr[0] = EGL_WAYLAND_PLANE_WL; |
||
598 | attr[1] = i; |
||
599 | attr[2] = EGL_NONE; |
||
600 | |||
601 | planar->image[i] = eglCreateImageKHR(px->dpy, px->context, |
||
602 | EGL_WAYLAND_BUFFER_WL,(EGLClientBuffer)name, attr); |
||
603 | |||
604 | glBindTexture(GL_TEXTURE_2D, planar->tex[i]); |
||
605 | |||
606 | glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, planar->image[i]); |
||
607 | |||
608 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_LINEAR); |
||
609 | glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_LINEAR); |
||
610 | }; |
||
611 | |||
612 | return planar; |
||
613 | |||
614 | err_0: |
||
615 | free(planar); |
||
616 | |||
617 | return NULL; |
||
618 | } |
||
619 | |||
620 | |||
5371 | serge | 621 | static int hw_destroy_bitmap(bitmap_t * bitmap) |
622 | { |
||
623 | struct drm_gem_close close; |
||
624 | |||
625 | glDeleteTextures(1, &bitmap->tex); |
||
626 | eglDestroyImageKHR(px->dpy, bitmap->image); |
||
627 | user_free(bitmap->buffer); |
||
628 | close.handle = bitmap->handle; |
||
629 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
630 | free(bitmap); |
||
631 | }; |
||
632 | |||
633 | static void *hw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch) |
||
634 | { |
||
635 | *pitch = bitmap->pitch; |
||
636 | |||
637 | return bitmap->buffer; |
||
638 | }; |
||
639 | |||
640 | static int hw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height) |
||
641 | { |
||
642 | return 0; |
||
643 | } |
||
644 | |||
645 | char proc_info[1024]; |
||
646 | |||
647 | static int hw_blit(bitmap_t *bitmap, int dst_x, int dst_y, |
||
648 | uint32_t w, uint32_t h, int src_x, int src_y) |
||
649 | { |
||
650 | struct drm_i915_mask_update update; |
||
651 | struct drm_i915_fb_info fb; |
||
652 | |||
653 | uint32_t winx, winy, winw, winh; |
||
654 | uint8_t state; |
||
655 | float xscale, yscale; |
||
656 | int r, b; |
||
657 | float *vertices = px->vertices; |
||
658 | |||
659 | get_proc_info(proc_info); |
||
660 | |||
661 | state = *(uint8_t*)(proc_info+70); |
||
662 | if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED)) |
||
663 | return; |
||
664 | |||
665 | winx = *(uint32_t*)(proc_info+34); |
||
666 | winy = *(uint32_t*)(proc_info+38); |
||
667 | winw = *(uint32_t*)(proc_info+42)+1; |
||
668 | winh = *(uint32_t*)(proc_info+46)+1; |
||
669 | |||
670 | __builtin_memset(&fb, 0, sizeof(fb)); |
||
671 | if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) |
||
672 | { |
||
673 | DBG("failed to get framebuffer info\n"); |
||
674 | return; |
||
675 | }; |
||
676 | |||
677 | if( fb.width != px->scr_width || |
||
678 | fb.height != px->scr_height ) |
||
679 | { |
||
680 | px->scr_width = fb.width; |
||
681 | px->scr_height = fb.height; |
||
682 | |||
683 | eglDestroyImageKHR(px->dpy, px->screen); |
||
684 | |||
685 | if(update_fb(px, fb.name, fb.pitch)) |
||
686 | return; |
||
687 | }; |
||
688 | |||
689 | update.handle = px->mask.handle; |
||
690 | update.dx = px->dx; |
||
691 | update.dy = px->dy; |
||
692 | update.width = px->width; |
||
693 | update.height = px->height; |
||
694 | update.bo_pitch = (px->width+15) & ~15; |
||
695 | update.bo_map = (int)px->mask.buffer; |
||
696 | |||
697 | if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update)) |
||
698 | { |
||
699 | return; |
||
700 | } |
||
701 | |||
702 | xscale = 1.0/px->scr_width; |
||
703 | yscale = 1.0/px->scr_height; |
||
704 | |||
705 | r = winx + px->dx + px->width; |
||
706 | b = winy + px->dy + px->height; |
||
707 | |||
708 | float t0, t1, t2, t5; |
||
709 | |||
710 | // render->tc_src[1*2] = 1.0; |
||
711 | // render->tc_src[2*2] = 1.0; |
||
712 | // render->tc_src[2*2+1]= 1.0; |
||
713 | // render->tc_src[3*2+1]= 1.0; |
||
714 | |||
715 | vertices[0] = t0 = 2*(winx+px->dx)*xscale - 1.0; |
||
716 | vertices[1 * 2] = t2 = 2*r*xscale - 1.0; |
||
717 | |||
718 | vertices[2 * 2] = t2; |
||
719 | vertices[3 * 2] = t0; |
||
720 | |||
721 | vertices[1] = t1 = 2*(winy+px->dy)*yscale - 1.0; |
||
722 | vertices[2*2+1] = t5 = 2*b*yscale - 1.0; |
||
723 | vertices[1*2+1] = t1; |
||
724 | vertices[3*2+1] = t5; |
||
725 | |||
726 | glActiveTexture(GL_TEXTURE0); |
||
727 | glBindTexture(GL_TEXTURE_2D, bitmap->tex); |
||
728 | |||
729 | glActiveTexture(GL_TEXTURE1); |
||
730 | glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]); |
||
731 | |||
732 | glDrawArrays(GL_TRIANGLE_FAN, 0, 4); |
||
733 | |||
734 | glFlush(); |
||
735 | |||
736 | return; |
||
737 | }; |
||
738 | |||
739 | static int hw_create_client(int x, int y, uint32_t width, uint32_t height) |
||
740 | { |
||
741 | px = create_render(eglGetCurrentDisplay(), eglGetCurrentContext(), x, y, width, height); |
||
742 | |||
743 | return !px; |
||
744 | }; |
||
745 | |||
746 | static int hw_resize_client(int x, int y, uint32_t width, uint32_t height) |
||
747 | { |
||
748 | if( x != px->dx || |
||
749 | y != px->dy || |
||
750 | width != px->width || |
||
751 | height != px->height ) |
||
752 | { |
||
753 | struct drm_i915_mask_update update; |
||
754 | |||
755 | px->dx = x; |
||
756 | px->dy = y; |
||
757 | px->width = width; |
||
758 | px->height = height; |
||
759 | update_mask(px); |
||
760 | |||
761 | update.handle = px->mask.handle; |
||
762 | update.dx = px->dx; |
||
763 | update.dy = px->dy; |
||
764 | update.width = px->width; |
||
765 | update.height = px->height; |
||
766 | update.bo_pitch = (px->width+15) & ~15; |
||
767 | update.bo_map = (int)px->mask.buffer; |
||
768 | update.forced = 1; |
||
769 | |||
770 | drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update); |
||
771 | }; |
||
772 | |||
773 | return 0; |
||
774 | }; |
||
775 | |||
776 | static void hw_fini(void) |
||
777 | { |
||
778 | struct drm_gem_close close; |
||
779 | |||
780 | DBG("%s\n", __FUNCTION__); |
||
781 | |||
782 | eglDestroyImageKHR(px->dpy, px->mask.image); |
||
783 | user_free(px->mask.buffer); |
||
784 | close.handle = px->mask.handle; |
||
785 | drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); |
||
786 | |||
787 | glBindFramebuffer(GL_FRAMEBUFFER, 0); |
||
788 | glDeleteFramebuffers(1, &px->framebuffer); |
||
789 | eglDestroyImageKHR(px->dpy, px->screen); |
||
790 | glDeleteTextures(2, px->texture); |
||
791 | egl_destroy(px->dpy, px->context); |
||
792 | free(px); |
||
793 | }; |
||
794 | |||
795 | static struct pix_driver gl_driver = |
||
796 | { |
||
797 | HW_TEX_BLIT, |
||
798 | hw_create_bitmap, |
||
799 | hw_destroy_bitmap, |
||
800 | hw_lock_bitmap, |
||
801 | hw_resize_bitmap, |
||
802 | hw_blit, |
||
803 | hw_create_client, |
||
804 | hw_resize_client, |
||
6115 | serge | 805 | hw_fini, |
806 | hw_create_planar |
||
5371 | serge | 807 | }; |
808 | |||
809 | struct pix_driver *DrvInit(uint32_t service) |
||
810 | { |
||
811 | EGLDisplay dpy; |
||
812 | EGLConfig config; |
||
813 | EGLContext context; |
||
814 | int ret; |
||
815 | |||
816 | ret = egl_initialize(&dpy, &config, &context); |
||
817 | if( ret ) |
||
818 | return NULL; |
||
819 | |||
820 | return &gl_driver; |
||
821 | |||
822 | err_0: |
||
823 | egl_destroy(dpy, context); |
||
824 | return NULL; |
||
825 | }> |
||
826 |