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_rect.h"
21 static drmModeModeInfoPtr
22 drm_find_mode(drmModeConnectorPtr connector
, _EGLMode
*mode
)
25 drmModeModeInfoPtr m
= NULL
;
27 for (i
= 0; i
< connector
->count_modes
; i
++) {
28 m
= &connector
->modes
[i
];
29 if (m
->hdisplay
== mode
->Width
&& m
->vdisplay
== mode
->Height
&& m
->vrefresh
== mode
->RefreshRate
)
31 m
= &connector
->modes
[0]; /* if we can't find one, return first */
37 static struct st_framebuffer
*
38 drm_create_framebuffer(const __GLcontextModes
*visual
,
43 enum pipe_format colorFormat
, depthFormat
, stencilFormat
;
45 if (visual
->redBits
== 5)
46 colorFormat
= PIPE_FORMAT_R5G6B5_UNORM
;
48 colorFormat
= PIPE_FORMAT_A8R8G8B8_UNORM
;
50 if (visual
->depthBits
== 16)
51 depthFormat
= PIPE_FORMAT_Z16_UNORM
;
52 else if (visual
->depthBits
== 24)
53 depthFormat
= PIPE_FORMAT_S8Z24_UNORM
;
55 depthFormat
= PIPE_FORMAT_NONE
;
57 if (visual
->stencilBits
== 8)
58 stencilFormat
= PIPE_FORMAT_S8Z24_UNORM
;
60 stencilFormat
= PIPE_FORMAT_NONE
;
62 return st_create_framebuffer(visual
,
72 drm_create_texture(_EGLDisplay
*dpy
,
73 struct drm_screen
*scrn
,
74 unsigned w
, unsigned h
)
76 struct drm_device
*dev
= lookup_drm_device(dpy
);
77 struct pipe_screen
*screen
= dev
->screen
;
78 struct pipe_surface
*surface
;
79 struct pipe_texture
*texture
;
80 struct pipe_texture templat
;
81 struct pipe_buffer
*buf
= NULL
;
84 memset(&templat
, 0, sizeof(templat
));
85 templat
.tex_usage
= PIPE_TEXTURE_USAGE_RENDER_TARGET
;
86 templat
.tex_usage
|= PIPE_TEXTURE_USAGE_PRIMARY
;
87 templat
.target
= PIPE_TEXTURE_2D
;
88 templat
.last_level
= 0;
90 templat
.format
= PIPE_FORMAT_A8R8G8B8_UNORM
;
92 templat
.height
[0] = h
;
93 pf_get_block(templat
.format
, &templat
.block
);
95 texture
= screen
->texture_create(dev
->screen
,
101 surface
= screen
->get_tex_surface(screen
,
106 PIPE_BUFFER_USAGE_GPU_WRITE
);
112 scrn
->surface
= surface
;
113 scrn
->front
.width
= w
;
114 scrn
->front
.height
= h
;
115 scrn
->front
.pitch
= pitch
;
116 dev
->api
->local_handle_from_texture(dev
->api
, screen
, texture
,
117 &scrn
->front
.pitch
, &scrn
->front
.handle
);
124 pipe_surface_reference(&surface
, NULL
);
126 pipe_texture_reference(&texture
, NULL
);
128 pipe_buffer_reference(&buf
, NULL
);
137 drm_takedown_shown_screen(_EGLDisplay
*dpy
, struct drm_screen
*screen
)
139 struct drm_device
*dev
= lookup_drm_device(dpy
);
148 NULL
, 0, // List of output ids
151 drmModeRmFB(dev
->drmFD
, screen
->fbID
);
152 drmModeFreeFB(screen
->fb
);
155 pipe_surface_reference(&screen
->surface
, NULL
);
156 pipe_texture_reference(&screen
->tex
, NULL
);
162 drm_create_window_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
, NativeWindowType window
, const EGLint
*attrib_list
)
169 drm_create_pixmap_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
, NativePixmapType pixmap
, const EGLint
*attrib_list
)
176 drm_create_pbuffer_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*conf
,
177 const EGLint
*attrib_list
)
182 struct drm_surface
*surf
= NULL
;
183 __GLcontextModes
*visual
;
185 for (i
= 0; attrib_list
&& attrib_list
[i
] != EGL_NONE
; i
++) {
186 switch (attrib_list
[i
]) {
188 width
= attrib_list
[++i
];
191 height
= attrib_list
[++i
];
194 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreatePbufferSurface");
195 return EGL_NO_SURFACE
;
199 if (width
< 1 || height
< 1) {
200 _eglError(EGL_BAD_ATTRIBUTE
, "eglCreatePbufferSurface");
204 surf
= (struct drm_surface
*) calloc(1, sizeof(struct drm_surface
));
208 if (!_eglInitSurface(drv
, &surf
->base
, EGL_PBUFFER_BIT
, conf
, attrib_list
))
214 visual
= drm_visual_from_config(conf
);
215 surf
->stfb
= drm_create_framebuffer(visual
,
219 drm_visual_modes_destroy(visual
);
230 drm_create_screen_surface_mesa(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLConfig
*cfg
,
231 const EGLint
*attrib_list
)
233 EGLSurface surf
= drm_create_pbuffer_surface(drv
, dpy
, cfg
, attrib_list
);
239 drm_show_screen_surface_mesa(_EGLDriver
*drv
, _EGLDisplay
*dpy
,
241 _EGLSurface
*surface
, _EGLMode
*mode
)
243 struct drm_device
*dev
= lookup_drm_device(dpy
);
244 struct drm_surface
*surf
= lookup_drm_surface(surface
);
245 struct drm_screen
*scrn
= lookup_drm_screen(screen
);
250 drm_takedown_shown_screen(dpy
, scrn
);
253 drm_create_texture(dpy
, scrn
, mode
->Width
, mode
->Height
);
257 ret
= drmModeAddFB(dev
->drmFD
,
258 scrn
->front
.width
, scrn
->front
.height
,
259 32, 32, scrn
->front
.pitch
,
266 scrn
->fb
= drmModeGetFB(dev
->drmFD
, scrn
->fbID
);
270 /* find a fitting crtc */
272 drmModeConnector
*con
= scrn
->connector
;
274 scrn
->mode
= drm_find_mode(con
, mode
);
278 for (k
= 0; k
< con
->count_encoders
; k
++) {
279 drmModeEncoder
*enc
= drmModeGetEncoder(dev
->drmFD
, con
->encoders
[k
]);
280 for (i
= 0; i
< dev
->res
->count_crtcs
; i
++) {
281 if (enc
->possible_crtcs
& (1<<i
)) {
283 scrn
->crtcID
= dev
->res
->crtcs
[i
];
286 i
= dev
->res
->count_crtcs
;
287 k
= dev
->res
->count_encoders
;
290 drmModeFreeEncoder(enc
);
294 ret
= drmModeSetCrtc(dev
->drmFD
,
298 &scrn
->connectorID
, 1,
306 drmModeConnectorSetProperty(dev
->drmFD
,
322 drmModeRmFB(dev
->drmFD
, scrn
->fbID
);
323 drmModeFreeFB(scrn
->fb
);
327 pipe_surface_reference(&scrn
->surface
, NULL
);
328 pipe_texture_reference(&scrn
->tex
, NULL
);
335 drm_destroy_surface(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*surface
)
337 struct drm_surface
*surf
= lookup_drm_surface(surface
);
338 if (!_eglIsSurfaceBound(&surf
->base
)) {
340 drm_takedown_shown_screen(dpy
, surf
->screen
);
341 st_unreference_framebuffer(surf
->stfb
);
348 drm_swap_buffers(_EGLDriver
*drv
, _EGLDisplay
*dpy
, _EGLSurface
*draw
)
350 struct drm_device
*dev
= lookup_drm_device(dpy
);
351 struct drm_surface
*surf
= lookup_drm_surface(draw
);
352 struct pipe_surface
*back_surf
;
357 st_get_framebuffer_surface(surf
->stfb
, ST_SURFACE_BACK_LEFT
, &back_surf
);
360 struct drm_context
*ctx
= lookup_drm_context(draw
->Binding
);
362 st_notify_swapbuffers(surf
->stfb
);
364 if (ctx
&& surf
->screen
) {
365 if (ctx
->pipe
->surface_copy
) {
366 ctx
->pipe
->surface_copy(ctx
->pipe
,
367 surf
->screen
->surface
,
373 util_surface_copy(ctx
->pipe
, FALSE
,
374 surf
->screen
->surface
,
380 ctx
->pipe
->flush(ctx
->pipe
, PIPE_FLUSH_RENDER_CACHE
| PIPE_FLUSH_TEXTURE_CACHE
, NULL
);
382 #ifdef DRM_MODE_FEATURE_DIRTYFB
383 /* TODO query connector property to see if this is needed */
384 drmModeDirtyFB(dev
->drmFD
, surf
->screen
->fbID
, NULL
, 0);
389 /* TODO more stuff here */