5 #include "egl_tracker.h"
9 #include "pipe/p_inlines.h"
10 #include "pipe/p_screen.h"
11 #include "pipe/p_context.h"
13 #include "state_tracker/drm_api.h"
15 #include "util/u_format.h"
16 #include "util/u_rect.h"
22 static drmModeModeInfoPtr
23 drm_find_mode(drmModeConnectorPtr connector
, _EGLMode
*mode
)
26 drmModeModeInfoPtr m
= NULL
;
28 for (i
= 0; i
< connector
->count_modes
; i
++) {
29 m
= &connector
->modes
[i
];
30 if (m
->hdisplay
== mode
->Width
&& m
->vdisplay
== mode
->Height
&& m
->vrefresh
== mode
->RefreshRate
)
32 m
= &connector
->modes
[0]; /* if we can't find one, return first */
38 static struct st_framebuffer
*
39 drm_create_framebuffer(struct pipe_screen
*screen
,
40 const __GLcontextModes
*visual
,
45 enum pipe_format color_format
, depth_stencil_format
;
46 boolean d_depth_bits_last
;
47 boolean ds_depth_bits_last
;
50 screen
->is_format_supported(screen
, PIPE_FORMAT_X8Z24_UNORM
,
52 PIPE_TEXTURE_USAGE_DEPTH_STENCIL
, 0);
54 screen
->is_format_supported(screen
, PIPE_FORMAT_S8Z24_UNORM
,
56 PIPE_TEXTURE_USAGE_DEPTH_STENCIL
, 0);
58 if (visual
->redBits
== 8) {
59 if (visual
->alphaBits
== 8)
60 color_format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
62 color_format
= PIPE_FORMAT_X8R8G8B8_UNORM
;
64 color_format
= PIPE_FORMAT_R5G6B5_UNORM
;
67 switch(visual
->depthBits
) {
70 depth_stencil_format
= PIPE_FORMAT_NONE
;
73 depth_stencil_format
= PIPE_FORMAT_Z16_UNORM
;
76 if (visual
->stencilBits
== 0) {
77 depth_stencil_format
= (d_depth_bits_last
) ?
78 PIPE_FORMAT_X8Z24_UNORM
:
79 PIPE_FORMAT_Z24X8_UNORM
;
81 depth_stencil_format
= (ds_depth_bits_last
) ?
82 PIPE_FORMAT_S8Z24_UNORM
:
83 PIPE_FORMAT_Z24S8_UNORM
;
87 depth_stencil_format
= PIPE_FORMAT_Z32_UNORM
;
91 return st_create_framebuffer(visual
,
101 drm_create_texture(_EGLDisplay
*dpy
,
102 struct drm_screen
*scrn
,
103 unsigned w
, unsigned h
)
105 struct drm_device
*dev
= lookup_drm_device(dpy
);
106 struct pipe_screen
*screen
= dev
->screen
;
107 struct pipe_surface
*surface
;
108 struct pipe_texture
*texture
;
109 struct pipe_texture templat
;
110 struct pipe_buffer
*buf
= NULL
;
113 memset(&templat
, 0, sizeof(templat
));
114 templat
.tex_usage
= PIPE_TEXTURE_USAGE_RENDER_TARGET
;
115 templat
.tex_usage
|= PIPE_TEXTURE_USAGE_PRIMARY
;
116 templat
.target
= PIPE_TEXTURE_2D
;
117 templat
.last_level
= 0;
119 templat
.format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
122 util_format_get_block(templat
.format
, &templat
.block
);
124 texture
= screen
->texture_create(dev
->screen
,
130 surface
= screen
->get_tex_surface(screen
,
135 PIPE_BUFFER_USAGE_GPU_WRITE
);
141 scrn
->surface
= surface
;
142 scrn
->front
.width
= w
;
143 scrn
->front
.height
= h
;
144 scrn
->front
.pitch
= pitch
;
145 dev
->api
->local_handle_from_texture(dev
->api
, screen
, texture
,
146 &scrn
->front
.pitch
, &scrn
->front
.handle
);
153 pipe_surface_reference(&surface
, NULL
);
155 pipe_texture_reference(&texture
, NULL
);
157 pipe_buffer_reference(&buf
, NULL
);
166 drm_takedown_shown_screen(_EGLDisplay
*dpy
, struct drm_screen
*screen
)
168 struct drm_device
*dev
= lookup_drm_device(dpy
);
177 NULL
, 0, // List of output ids
180 drmModeRmFB(dev
->drmFD
, screen
->fbID
);
181 drmModeFreeFB(screen
->fb
);
184 pipe_surface_reference(&screen
->surface
, NULL
);
185 pipe_texture_reference(&screen
->tex
, NULL
);
191 * Called by libEGL's eglCreateWindowSurface().
194 drm_create_window_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
, NativeWindowType window
, const EGLint
*attrib_list
)
201 * Called by libEGL's eglCreatePixmapSurface().
204 drm_create_pixmap_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
, NativePixmapType pixmap
, const EGLint
*attrib_list
)
211 * Called by libEGL's eglCreatePbufferSurface().
214 drm_create_pbuffer_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
215 const EGLint
*attrib_list
)
217 struct drm_device
*dev
= lookup_drm_device(dpy
);
221 struct drm_surface
*surf
= NULL
;
222 __GLcontextModes
*visual
;
224 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
225 switch (attrib_list
[i
]) {
227 width
= attrib_list
[++i
];
230 height
= attrib_list
[++i
];
233 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreatePbufferSurface");
234 return EGL_NO_SURFACE
;
238 if (width
< 1 || height
< 1) {
239 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreatePbufferSurface");
243 surf
= (struct drm_surface
*) calloc(1, sizeof(struct drm_surface
));
247 if (!_eglInitSurface(drv
, &surf
->base
, EGL_PBUFFER_BIT
, conf
, attrib_list
))
253 visual
= drm_visual_from_config(conf
);
254 surf
->stfb
= drm_create_framebuffer(dev
->screen
, visual
,
257 drm_visual_modes_destroy(visual
);
268 * Called by libEGL's eglCreateScreenSurfaceMESA().
271 drm_create_screen_surface_mesa(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*cfg
,
272 const EGLint
*attrib_list
)
274 EGLSurface surf
= drm_create_pbuffer_surface(drv
, dpy
, cfg
, attrib_list
);
280 * Called by libEGL's eglShowScreenSurfaceMESA().
283 drm_show_screen_surface_mesa(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
285 _EGLSurface
*surface
, _EGLMode
*mode
)
287 struct drm_device
*dev
= lookup_drm_device(dpy
);
288 struct drm_surface
*surf
= lookup_drm_surface(surface
);
289 struct drm_screen
*scrn
= lookup_drm_screen(screen
);
294 drm_takedown_shown_screen(dpy
, scrn
);
297 drm_create_texture(dpy
, scrn
, mode
->Width
, mode
->Height
);
301 ret
= drmModeAddFB(dev
->drmFD
,
302 scrn
->front
.width
, scrn
->front
.height
,
303 32, 32, scrn
->front
.pitch
,
310 scrn
->fb
= drmModeGetFB(dev
->drmFD
, scrn
->fbID
);
314 /* find a fitting crtc */
316 drmModeConnector
*con
= scrn
->connector
;
318 scrn
->mode
= drm_find_mode(con
, mode
);
322 for (k
= 0; k
< con
->count_encoders
; k
++) {
323 drmModeEncoder
*enc
= drmModeGetEncoder(dev
->drmFD
, con
->encoders
[k
]);
324 for (i
= 0; i
< dev
->res
->count_crtcs
; i
++) {
325 if (enc
->possible_crtcs
& (1<<i
)) {
327 scrn
->crtcID
= dev
->res
->crtcs
[i
];
330 i
= dev
->res
->count_crtcs
;
331 k
= dev
->res
->count_encoders
;
334 drmModeFreeEncoder(enc
);
338 ret
= drmModeSetCrtc(dev
->drmFD
,
342 &scrn
->connectorID
, 1,
350 drmModeConnectorSetProperty(dev
->drmFD
,
366 drmModeRmFB(dev
->drmFD
, scrn
->fbID
);
367 drmModeFreeFB(scrn
->fb
);
371 pipe_surface_reference(&scrn
->surface
, NULL
);
372 pipe_texture_reference(&scrn
->tex
, NULL
);
379 * Called by libEGL's eglDestroySurface().
382 drm_destroy_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
)
384 struct drm_surface
*surf
= lookup_drm_surface(surface
);
385 if (!_eglIsSurfaceBound(&surf
->base
)) {
387 drm_takedown_shown_screen(dpy
, surf
->screen
);
388 st_unreference_framebuffer(surf
->stfb
);
395 * Called by libEGL's eglSwapBuffers().
398 drm_swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*draw
)
400 struct drm_device
*dev
= lookup_drm_device(dpy
);
401 struct drm_surface
*surf
= lookup_drm_surface(draw
);
402 struct pipe_surface
*back_surf
;
407 st_get_framebuffer_surface(surf
->stfb
, ST_SURFACE_BACK_LEFT
, &back_surf
);
410 struct drm_context
*ctx
= lookup_drm_context(draw
->Binding
);
412 st_notify_swapbuffers(surf
->stfb
);
414 if (ctx
&& surf
->screen
) {
415 if (ctx
->pipe
->surface_copy
) {
416 ctx
->pipe
->surface_copy(ctx
->pipe
,
417 surf
->screen
->surface
,
423 util_surface_copy(ctx
->pipe
, FALSE
,
424 surf
->screen
->surface
,
430 ctx
->pipe
->flush(ctx
->pipe
, PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_TEXTURE_CACHE
, NULL
);
432 #ifdef DRM_MODE_FEATURE_DIRTYFB
433 /* TODO query connector property to see if this is needed */
434 drmModeDirtyFB(dev
->drmFD
, surf
->screen
->fbID
, NULL
, 0);
439 /* TODO more stuff here */