egl: Add a egl state_tracker that use Gallium

This works on top Gallium and KMS. The only thing that
	does not work currently is swap buffers for shown mesa
	screens. So the only fun thing this will produce is a
	white screen.

	The driver wishing to us the state_tracker needs to
	implement the intrace as define in drm_api.h located
	in gallium/include/state_tracker. And also have a
	working KMS implementation.
This commit is contained in:
Jakob Bornecrantz 2009-01-18 15:36:47 +01:00
parent a874cf37ee
commit 7047f1755f
7 changed files with 1067 additions and 0 deletions

View file

@ -0,0 +1,33 @@
#ifndef _DRM_API_H_
#define _DRM_API_H_
struct pipe_screen;
struct pipe_winsys;
struct pipe_context;
struct drm_api
{
/**
* Special buffer function
*/
/*@{*/
struct pipe_screen* (*create_screen)(int drmFB, int pciID);
struct pipe_context* (*create_context)(struct pipe_screen *screen);
/*@}*/
/**
* Special buffer function
*/
/*@{*/
struct pipe_buffer* (*buffer_from_handle)(struct pipe_winsys *winsys, const char *name, unsigned handle);
unsigned (*handle_from_buffer)(struct pipe_winsys *winsys, struct pipe_buffer *buffer);
/*@}*/
};
/**
* A driver needs to export this symbol
*/
extern struct drm_api drm_api_hocks;
#endif

View file

@ -0,0 +1,29 @@
TARGET = libegldrm.a
CFILES = $(wildcard ./*.c)
OBJECTS = $(patsubst ./%.c,./%.o,$(CFILES))
GALLIUMDIR = ../..
TOP = ../../../..
include ${TOP}/configs/current
CFLAGS += -g -Wall -Werror=implicit-function-declaration -fPIC \
$(shell pkg-config --cflags pixman-1 xorg-server) \
-I${GALLIUMDIR}/include \
-I${GALLIUMDIR}/auxiliary \
-I${TOP}/src/mesa/drivers/dri/common \
-I${TOP}/src/mesa \
-I$(TOP)/include \
-I$(TOP)/src/egl/main \
${LIBDRM_CFLAGS}
#############################################
.PHONY = all clean
all: ${TARGET}
${TARGET}: ${OBJECTS}
ar rcs $@ $^
clean:
rm -rf ${OBJECTS} ${TARGET}

View file

@ -0,0 +1,194 @@
#include "utils.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "egl_tracker.h"
#include "egllog.h"
#include "pipe/p_context.h"
#include "pipe/p_screen.h"
#include "pipe/p_winsys.h"
#include "state_tracker/st_public.h"
#include "state_tracker/drm_api.h"
#include "GL/internal/glcore.h"
#define need_GL_ARB_multisample
#define need_GL_ARB_point_parameters
#define need_GL_ARB_texture_compression
#define need_GL_ARB_vertex_buffer_object
#define need_GL_ARB_vertex_program
#define need_GL_ARB_window_pos
#define need_GL_EXT_blend_color
#define need_GL_EXT_blend_equation_separate
#define need_GL_EXT_blend_func_separate
#define need_GL_EXT_blend_minmax
#define need_GL_EXT_cull_vertex
#define need_GL_EXT_fog_coord
#define need_GL_EXT_framebuffer_object
#define need_GL_EXT_multi_draw_arrays
#define need_GL_EXT_secondary_color
#define need_GL_NV_vertex_program
#include "extension_helper.h"
/**
* TODO HACK! FUGLY!
* Copied for intel extentions.
*/
const struct dri_extension card_extensions[] = {
{"GL_ARB_multisample", GL_ARB_multisample_functions},
{"GL_ARB_multitexture", NULL},
{"GL_ARB_point_parameters", GL_ARB_point_parameters_functions},
{"GL_ARB_texture_border_clamp", NULL},
{"GL_ARB_texture_compression", GL_ARB_texture_compression_functions},
{"GL_ARB_texture_cube_map", NULL},
{"GL_ARB_texture_env_add", NULL},
{"GL_ARB_texture_env_combine", NULL},
{"GL_ARB_texture_env_dot3", NULL},
{"GL_ARB_texture_mirrored_repeat", NULL},
{"GL_ARB_texture_rectangle", NULL},
{"GL_ARB_vertex_buffer_object", GL_ARB_vertex_buffer_object_functions},
{"GL_ARB_pixel_buffer_object", NULL},
{"GL_ARB_vertex_program", GL_ARB_vertex_program_functions},
{"GL_ARB_window_pos", GL_ARB_window_pos_functions},
{"GL_EXT_blend_color", GL_EXT_blend_color_functions},
{"GL_EXT_blend_equation_separate", GL_EXT_blend_equation_separate_functions},
{"GL_EXT_blend_func_separate", GL_EXT_blend_func_separate_functions},
{"GL_EXT_blend_minmax", GL_EXT_blend_minmax_functions},
{"GL_EXT_blend_subtract", NULL},
{"GL_EXT_cull_vertex", GL_EXT_cull_vertex_functions},
{"GL_EXT_fog_coord", GL_EXT_fog_coord_functions},
{"GL_EXT_framebuffer_object", GL_EXT_framebuffer_object_functions},
{"GL_EXT_multi_draw_arrays", GL_EXT_multi_draw_arrays_functions},
{"GL_EXT_packed_depth_stencil", NULL},
{"GL_EXT_pixel_buffer_object", NULL},
{"GL_EXT_secondary_color", GL_EXT_secondary_color_functions},
{"GL_EXT_stencil_wrap", NULL},
{"GL_EXT_texture_edge_clamp", NULL},
{"GL_EXT_texture_env_combine", NULL},
{"GL_EXT_texture_env_dot3", NULL},
{"GL_EXT_texture_filter_anisotropic", NULL},
{"GL_EXT_texture_lod_bias", NULL},
{"GL_3DFX_texture_compression_FXT1", NULL},
{"GL_APPLE_client_storage", NULL},
{"GL_MESA_pack_invert", NULL},
{"GL_MESA_ycbcr_texture", NULL},
{"GL_NV_blend_square", NULL},
{"GL_NV_vertex_program", GL_NV_vertex_program_functions},
{"GL_NV_vertex_program1_1", NULL},
{"GL_SGIS_generate_mipmap", NULL },
{NULL, NULL}
};
EGLContext
drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list)
{
struct drm_device *dev = (struct drm_device *)drv;
struct drm_context *ctx;
struct drm_context *share = NULL;
struct st_context *st_share = NULL;
_EGLConfig *conf;
int i;
__GLcontextModes *visual;
conf = _eglLookupConfig(drv, dpy, config);
if (!conf) {
_eglError(EGL_BAD_CONFIG, "eglCreateContext");
return EGL_NO_CONTEXT;
}
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
switch (attrib_list[i]) {
/* no attribs defined for now */
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglCreateContext");
return EGL_NO_CONTEXT;
}
}
ctx = (struct drm_context *) calloc(1, sizeof(struct drm_context));
if (!ctx)
goto err_c;
_eglInitContext(drv, dpy, &ctx->base, config, attrib_list);
ctx->pipe = drm_api_hocks.create_context(dev->screen);
if (!ctx->pipe)
goto err_pipe;
if (share)
st_share = share->st;
visual = drm_visual_from_config(conf);
ctx->st = st_create_context(ctx->pipe, visual, st_share);
drm_visual_modes_destroy(visual);
if (!ctx->st)
goto err_gl;
/* generate handle and insert into hash table */
_eglSaveContext(&ctx->base);
assert(_eglGetContextHandle(&ctx->base));
return _eglGetContextHandle(&ctx->base);
err_gl:
ctx->pipe->destroy(ctx->pipe);
err_pipe:
free(ctx);
err_c:
return EGL_NO_CONTEXT;
}
EGLBoolean
drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context)
{
struct drm_context *c = lookup_drm_context(context);
_eglRemoveContext(&c->base);
if (c->base.IsBound) {
c->base.DeletePending = EGL_TRUE;
} else {
st_destroy_context(c->st);
c->pipe->destroy(c->pipe);
free(c);
}
return EGL_TRUE;
}
EGLBoolean
drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context)
{
struct drm_surface *readSurf = lookup_drm_surface(read);
struct drm_surface *drawSurf = lookup_drm_surface(draw);
struct drm_context *ctx = lookup_drm_context(context);
EGLBoolean b;
b = _eglMakeCurrent(drv, dpy, draw, read, context);
if (!b)
return EGL_FALSE;
if (ctx) {
if (!drawSurf || !readSurf)
return EGL_FALSE;
drawSurf->user = ctx;
readSurf->user = ctx;
st_make_current(ctx->st, drawSurf->stfb, readSurf->stfb);
/* st_resize_framebuffer needs a bound context to work */
st_resize_framebuffer(drawSurf->stfb, drawSurf->w, drawSurf->h);
st_resize_framebuffer(readSurf->stfb, readSurf->w, readSurf->h);
} else {
drawSurf->user = NULL;
readSurf->user = NULL;
st_make_current(NULL, NULL, NULL);
}
return EGL_TRUE;
}

View file

@ -0,0 +1,324 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "egl_tracker.h"
#include "egllog.h"
#include "pipe/p_inlines.h"
#include "state_tracker/drm_api.h"
/*
* Util functions
*/
static struct drm_mode_modeinfo *
drm_find_mode(drmModeConnectorPtr connector, _EGLMode *mode)
{
int i;
struct drm_mode_modeinfo *m = NULL;
for (i = 0; i < connector->count_modes; i++) {
m = &connector->modes[i];
if (m->hdisplay == mode->Width && m->vdisplay == mode->Height && m->vrefresh == mode->RefreshRate)
break;
m = &connector->modes[0]; /* if we can't find one, return first */
}
return m;
}
static struct st_framebuffer *
drm_create_framebuffer(const __GLcontextModes *visual,
unsigned width,
unsigned height,
void *priv)
{
enum pipe_format colorFormat, depthFormat, stencilFormat;
if (visual->redBits == 5)
colorFormat = PIPE_FORMAT_R5G6B5_UNORM;
else
colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM;
if (visual->depthBits == 16)
depthFormat = PIPE_FORMAT_Z16_UNORM;
else if (visual->depthBits == 24)
depthFormat = PIPE_FORMAT_S8Z24_UNORM;
else
depthFormat = PIPE_FORMAT_NONE;
if (visual->stencilBits == 8)
stencilFormat = PIPE_FORMAT_S8Z24_UNORM;
else
stencilFormat = PIPE_FORMAT_NONE;
return st_create_framebuffer(visual,
colorFormat,
depthFormat,
stencilFormat,
width,
height,
priv);
}
/*
* Exported functions
*/
void
drm_takedown_shown_screen(_EGLDriver *drv, struct drm_screen *screen)
{
struct drm_device *dev = (struct drm_device *)drv;
screen->surf = NULL;
drmModeSetCrtc(
dev->drmFD,
screen->crtcID,
0, // FD
0, 0,
NULL, 0, // List of output ids
NULL);
drmModeRmFB(dev->drmFD, screen->fbID);
drmModeFreeFB(screen->fb);
screen->fb = NULL;
pipe_buffer_reference(dev->screen, &screen->buffer, NULL);
screen->shown = 0;
}
EGLSurface
drm_create_window_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list)
{
return EGL_NO_SURFACE;
}
EGLSurface
drm_create_pixmap_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list)
{
return EGL_NO_SURFACE;
}
EGLSurface
drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config,
const EGLint *attrib_list)
{
int i;
int width = -1;
int height = -1;
struct drm_surface *surf = NULL;
__GLcontextModes *visual;
_EGLConfig *conf;
conf = _eglLookupConfig(drv, dpy, config);
if (!conf) {
_eglError(EGL_BAD_CONFIG, "eglCreatePbufferSurface");
return EGL_NO_CONTEXT;
}
for (i = 0; attrib_list && attrib_list[i] != EGL_NONE; i++) {
switch (attrib_list[i]) {
case EGL_WIDTH:
width = attrib_list[++i];
break;
case EGL_HEIGHT:
height = attrib_list[++i];
break;
default:
_eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface");
return EGL_NO_SURFACE;
}
}
if (width < 1 || height < 1) {
_eglError(EGL_BAD_ATTRIBUTE, "eglCreatePbufferSurface");
return EGL_NO_SURFACE;
}
surf = (struct drm_surface *) calloc(1, sizeof(struct drm_surface));
if (!surf)
goto err;
if (!_eglInitSurface(drv, dpy, &surf->base, EGL_PBUFFER_BIT, config, attrib_list))
goto err_surf;
surf->w = width;
surf->h = height;
visual = drm_visual_from_config(conf);
surf->stfb = drm_create_framebuffer(visual,
width,
height,
(void*)surf);
drm_visual_modes_destroy(visual);
_eglSaveSurface(&surf->base);
return surf->base.Handle;
err_surf:
free(surf);
err:
return EGL_NO_SURFACE;
}
EGLSurface
drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg,
const EGLint *attrib_list)
{
EGLSurface surf = drm_create_pbuffer_surface(drv, dpy, cfg, attrib_list);
return surf;
}
EGLBoolean
drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy,
EGLScreenMESA screen,
EGLSurface surface, EGLModeMESA m)
{
struct drm_device *dev = (struct drm_device *)drv;
struct drm_surface *surf = lookup_drm_surface(surface);
struct drm_screen *scrn = lookup_drm_screen(dpy, screen);
_EGLMode *mode = _eglLookupMode(dpy, m);
size_t pitch = 2048 * 4;
size_t size = mode->Height * pitch;
int ret;
unsigned int i, k;
void *ptr;
if (scrn->shown)
drm_takedown_shown_screen(drv, scrn);
scrn->buffer = pipe_buffer_create(dev->screen,
0, /* alignment */
PIPE_BUFFER_USAGE_GPU_READ_WRITE |
PIPE_BUFFER_USAGE_CPU_READ_WRITE,
size);
if (!scrn->buffer)
return EGL_FALSE;
ptr = pipe_buffer_map(dev->screen, scrn->buffer, PIPE_BUFFER_USAGE_CPU_WRITE);
memset(ptr, 0xFF, size);
pipe_buffer_unmap(dev->screen, scrn->buffer);
scrn->handle = drm_api_hocks.handle_from_buffer(dev->winsys, scrn->buffer);
ret = drmModeAddFB(dev->drmFD, mode->Width, mode->Height,
32, 32, pitch,
scrn->handle,
&scrn->fbID);
if (ret)
goto err_bo;
scrn->fb = drmModeGetFB(dev->drmFD, scrn->fbID);
if (!scrn->fb)
goto err_bo;
/* find a fitting crtc */
{
drmModeConnector *con = scrn->connector;
scrn->mode = drm_find_mode(con, mode);
if (!scrn->mode)
goto err_fb;
for (k = 0; k < con->count_encoders; k++) {
drmModeEncoder *enc = drmModeGetEncoder(dev->drmFD, con->encoders[k]);
for (i = 0; i < dev->res->count_crtcs; i++) {
if (enc->possible_crtcs & (1<<i)) {
/* save the ID */
scrn->crtcID = dev->res->crtcs[i];
/* skip the rest */
i = dev->res->count_crtcs;
k = dev->res->count_encoders;
}
}
drmModeFreeEncoder(enc);
}
}
ret = drmModeSetCrtc(dev->drmFD,
scrn->crtcID,
scrn->fbID,
0, 0,
&scrn->connectorID, 1,
scrn->mode);
if (ret)
goto err_crtc;
surf->screen = scrn;
scrn->surf = surf;
scrn->shown = 1;
return EGL_TRUE;
err_crtc:
scrn->crtcID = 0;
err_fb:
drmModeRmFB(dev->drmFD, scrn->fbID);
drmModeFreeFB(scrn->fb);
scrn->fb = NULL;
err_bo:
pipe_buffer_reference(dev->screen, &scrn->buffer, NULL);
return EGL_FALSE;
}
EGLBoolean
drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface)
{
struct drm_surface *surf = lookup_drm_surface(surface);
_eglRemoveSurface(&surf->base);
if (surf->base.IsBound) {
surf->base.DeletePending = EGL_TRUE;
} else {
if (surf->screen)
drm_takedown_shown_screen(drv, surf->screen);
st_unreference_framebuffer(surf->stfb);
free(surf);
}
return EGL_TRUE;
}
EGLBoolean
drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw)
{
struct drm_surface *surf = lookup_drm_surface(draw);
struct pipe_surface *back_surf;
if (!surf)
return EGL_FALSE;
/* error checking */
if (!_eglSwapBuffers(drv, dpy, draw))
return EGL_FALSE;
back_surf = st_get_framebuffer_surface(surf->stfb,
ST_SURFACE_BACK_LEFT);
if (back_surf) {
st_notify_swapbuffers(surf->stfb);
if (surf->screen) {
/* TODO stuff here */
}
st_notify_swapbuffers_complete(surf->stfb);
}
return EGL_TRUE;
}

View file

@ -0,0 +1,217 @@
#include "utils.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "egl_tracker.h"
#include "egllog.h"
#include "state_tracker/drm_api.h"
#include "pipe/p_screen.h"
#include "pipe/p_winsys.h"
/** HACK */
void* driDriverAPI;
extern const struct dri_extension card_extensions[];
/*
* Exported functions
*/
/**
* The bootstrap function. Return a new drm_driver object and
* plug in API functions.
*/
_EGLDriver *
_eglMain(_EGLDisplay *dpy, const char *args)
{
struct drm_device *drm;
drm = (struct drm_device *) calloc(1, sizeof(struct drm_device));
if (!drm) {
return NULL;
}
/* First fill in the dispatch table with defaults */
_eglInitDriverFallbacks(&drm->base);
/* then plug in our Drm-specific functions */
drm->base.API.Initialize = drm_initialize;
drm->base.API.Terminate = drm_terminate;
drm->base.API.CreateContext = drm_create_context;
drm->base.API.MakeCurrent = drm_make_current;
drm->base.API.CreateWindowSurface = drm_create_window_surface;
drm->base.API.CreatePixmapSurface = drm_create_pixmap_surface;
drm->base.API.CreatePbufferSurface = drm_create_pbuffer_surface;
drm->base.API.DestroySurface = drm_destroy_surface;
drm->base.API.DestroyContext = drm_destroy_context;
drm->base.API.CreateScreenSurfaceMESA = drm_create_screen_surface_mesa;
drm->base.API.ShowScreenSurfaceMESA = drm_show_screen_surface_mesa;
drm->base.API.SwapBuffers = drm_swap_buffers;
drm->base.ClientAPIsMask = EGL_OPENGL_BIT /*| EGL_OPENGL_ES_BIT*/;
drm->base.Name = "DRM/Gallium/Win";
/* enable supported extensions */
drm->base.Extensions.MESA_screen_surface = EGL_TRUE;
drm->base.Extensions.MESA_copy_context = EGL_TRUE;
return &drm->base;
}
static void
drm_get_device_id(struct drm_device *device)
{
char path[512];
FILE *file;
/* TODO get the real minor */
int minor = 0;
snprintf(path, sizeof(path), "/sys/class/drm/card%d/device/device", minor);
file = fopen(path, "r");
if (!file) {
_eglLog(_EGL_WARNING, "Could not retrive device ID\n");
return;
}
fgets(path, sizeof( path ), file);
sscanf(path, "%x", &device->deviceID);
fclose(file);
}
static void
drm_update_res(struct drm_device *dev)
{
drmModeFreeResources(dev->res);
dev->res = drmModeGetResources(dev->drmFD);
}
static void
drm_add_modes_from_connector(_EGLScreen *screen, drmModeConnectorPtr connector)
{
struct drm_mode_modeinfo *m;
int i;
for (i = 0; i < connector->count_modes; i++) {
m = &connector->modes[i];
_eglAddNewMode(screen, m->hdisplay, m->vdisplay, m->vrefresh, m->name);
}
}
EGLBoolean
drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor)
{
_EGLDisplay *disp = _eglLookupDisplay(dpy);
struct drm_device *dev = (struct drm_device *)drv;
struct drm_screen *screen = NULL;
drmModeConnectorPtr connector = NULL;
drmModeResPtr res = NULL;
unsigned count_connectors = 0;
int num_screens = 0;
EGLint i;
int fd;
fd = drmOpen("i915", NULL);
if (fd < 0)
goto err_fd;
dev->drmFD = fd;
drm_get_device_id(dev);
dev->screen = drm_api_hocks.create_screen(dev->drmFD, dev->deviceID);
if (!dev->screen)
goto err_screen;
dev->winsys = dev->screen->winsys;
/* TODO HACK */
driInitExtensions(NULL, card_extensions, GL_FALSE);
drm_update_res(dev);
res = dev->res;
if (res)
count_connectors = res->count_connectors;
else
_eglLog(_EGL_WARNING, "Could not retrive kms information\n");
for(i = 0; i < count_connectors && i < MAX_SCREENS; i++) {
connector = drmModeGetConnector(fd, res->connectors[i]);
if (!connector)
continue;
if (connector->connection != DRM_MODE_CONNECTED) {
drmModeFreeConnector(connector);
continue;
}
screen = malloc(sizeof(struct drm_screen));
memset(screen, 0, sizeof(*screen));
screen->connector = connector;
screen->connectorID = connector->connector_id;
_eglInitScreen(&screen->base);
_eglAddScreen(disp, &screen->base);
drm_add_modes_from_connector(&screen->base, connector);
dev->screens[num_screens++] = screen;
}
dev->count_screens = num_screens;
/* for now we only have one config */
_EGLConfig *config = calloc(1, sizeof(*config));
memset(config, 1, sizeof(*config));
_eglInitConfig(config, 1);
_eglSetConfigAttrib(config, EGL_RED_SIZE, 8);
_eglSetConfigAttrib(config, EGL_GREEN_SIZE, 8);
_eglSetConfigAttrib(config, EGL_BLUE_SIZE, 8);
_eglSetConfigAttrib(config, EGL_ALPHA_SIZE, 8);
_eglSetConfigAttrib(config, EGL_BUFFER_SIZE, 32);
_eglSetConfigAttrib(config, EGL_DEPTH_SIZE, 24);
_eglSetConfigAttrib(config, EGL_STENCIL_SIZE, 8);
_eglSetConfigAttrib(config, EGL_SURFACE_TYPE, EGL_PBUFFER_BIT);
_eglAddConfig(disp, config);
drv->Initialized = EGL_TRUE;
*major = 1;
*minor = 4;
return EGL_TRUE;
err_screen:
drmClose(fd);
err_fd:
return EGL_FALSE;
}
EGLBoolean
drm_terminate(_EGLDriver *drv, EGLDisplay dpy)
{
struct drm_device *dev = (struct drm_device *)drv;
struct drm_screen *screen;
int i = 0;
drmFreeVersion(dev->version);
for (i = 0; i < dev->count_screens; i++) {
screen = dev->screens[i];
if (screen->shown)
drm_takedown_shown_screen(drv, screen);
drmModeFreeConnector(screen->connector);
_eglDestroyScreen(&screen->base);
dev->screens[i] = NULL;
}
dev->screen->destroy(dev->screen);
dev->winsys = NULL;
drmClose(dev->drmFD);
_eglCleanupDisplay(_eglLookupDisplay(dpy));
free(dev);
return EGL_TRUE;
}

View file

@ -0,0 +1,185 @@
#ifndef _EGL_TRACKER_H_
#define _EGL_TRACKER_H_
#include <stdint.h>
#include "eglconfig.h"
#include "eglcontext.h"
#include "egldisplay.h"
#include "egldriver.h"
#include "eglglobals.h"
#include "eglmode.h"
#include "eglscreen.h"
#include "eglsurface.h"
#include "xf86drm.h"
#include "xf86drmMode.h"
#include "pipe/p_compiler.h"
#include "state_tracker/st_public.h"
#define MAX_SCREENS 16
struct pipe_winsys;
struct pipe_screen;
struct pipe_context;
struct state_tracker;
struct drm_screen;
struct drm_context;
struct drm_device
{
_EGLDriver base; /* base class/object */
/*
* pipe
*/
struct pipe_winsys *winsys;
struct pipe_screen *screen;
/*
* drm
*/
int drmFD;
drmVersionPtr version;
int deviceID;
drmModeResPtr res;
struct drm_screen *screens[MAX_SCREENS];
size_t count_screens;
};
struct drm_surface
{
_EGLSurface base; /* base class/object */
/*
* pipe
*/
struct st_framebuffer *stfb;
/*
* drm
*/
struct drm_context *user;
struct drm_screen *screen;
int w;
int h;
};
struct drm_context
{
_EGLContext base; /* base class/object */
/* pipe */
struct pipe_context *pipe;
struct st_context *st;
};
struct drm_screen
{
_EGLScreen base;
/*
* pipe
*/
struct pipe_buffer *buffer;
/*
* drm
*/
/* buffer handle */
int handle;
/* currently only support one connector */
drmModeConnectorPtr connector;
uint32_t connectorID;
/* Has this screen been shown */
int shown;
/* Surface that is currently attached to this screen */
struct drm_surface *surf;
/* framebuffer */
drmModeFBPtr fb;
uint32_t fbID;
/* crtc and mode used */
/*drmModeCrtcPtr crtc;*/
uint32_t crtcID;
struct drm_mode_modeinfo *mode;
};
static INLINE struct drm_context *
lookup_drm_context(EGLContext context)
{
_EGLContext *c = _eglLookupContext(context);
return (struct drm_context *) c;
}
static INLINE struct drm_surface *
lookup_drm_surface(EGLSurface surface)
{
_EGLSurface *s = _eglLookupSurface(surface);
return (struct drm_surface *) s;
}
static INLINE struct drm_screen *
lookup_drm_screen(EGLDisplay dpy, EGLScreenMESA screen)
{
_EGLScreen *s = _eglLookupScreen(dpy, screen);
return (struct drm_screen *) s;
}
/**
* egl_visual.h
*/
/*@{*/
void drm_visual_modes_destroy(__GLcontextModes *modes);
__GLcontextModes* drm_visual_modes_create(unsigned count, size_t minimum_size);
__GLcontextModes* drm_visual_from_config(_EGLConfig *conf);
/*@}*/
/**
* egl_surface.h
*/
/*@{*/
void drm_takedown_shown_screen(_EGLDriver *drv, struct drm_screen *screen);
/*@}*/
/**
* All function exported to the egl side.
*/
/*@{*/
EGLBoolean drm_initialize(_EGLDriver *drv, EGLDisplay dpy, EGLint *major, EGLint *minor);
EGLBoolean drm_terminate(_EGLDriver *drv, EGLDisplay dpy);
EGLContext drm_create_context(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, EGLContext share_list, const EGLint *attrib_list);
EGLBoolean drm_destroy_context(_EGLDriver *drv, EGLDisplay dpy, EGLContext context);
EGLSurface drm_create_window_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativeWindowType window, const EGLint *attrib_list);
EGLSurface drm_create_pixmap_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, NativePixmapType pixmap, const EGLint *attrib_list);
EGLSurface drm_create_pbuffer_surface(_EGLDriver *drv, EGLDisplay dpy, EGLConfig config, const EGLint *attrib_list);
EGLSurface drm_create_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLConfig cfg, const EGLint *attrib_list);
EGLBoolean drm_show_screen_surface_mesa(_EGLDriver *drv, EGLDisplay dpy, EGLScreenMESA screen, EGLSurface surface, EGLModeMESA m);
EGLBoolean drm_destroy_surface(_EGLDriver *drv, EGLDisplay dpy, EGLSurface surface);
EGLBoolean drm_make_current(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw, EGLSurface read, EGLContext context);
EGLBoolean drm_swap_buffers(_EGLDriver *drv, EGLDisplay dpy, EGLSurface draw);
/*@}*/
#endif

View file

@ -0,0 +1,85 @@
#include "egl_tracker.h"
#include "egllog.h"
void
drm_visual_modes_destroy(__GLcontextModes *modes)
{
_eglLog(_EGL_DEBUG, "%s", __FUNCTION__);
while (modes) {
__GLcontextModes * const next = modes->next;
free(modes);
modes = next;
}
}
__GLcontextModes *
drm_visual_modes_create(unsigned count, size_t minimum_size)
{
/* This code copied from libGLX, and modified */
const size_t size = (minimum_size > sizeof(__GLcontextModes))
? minimum_size : sizeof(__GLcontextModes);
__GLcontextModes * head = NULL;
__GLcontextModes ** next;
unsigned i;
_eglLog(_EGL_DEBUG, "%s %d %d", __FUNCTION__, count, minimum_size);
next = & head;
for (i = 0 ; i < count ; i++) {
*next = (__GLcontextModes *) calloc(1, size);
if (*next == NULL) {
drm_visual_modes_destroy(head);
head = NULL;
break;
}
(*next)->doubleBufferMode = 1;
(*next)->visualID = GLX_DONT_CARE;
(*next)->visualType = GLX_DONT_CARE;
(*next)->visualRating = GLX_NONE;
(*next)->transparentPixel = GLX_NONE;
(*next)->transparentRed = GLX_DONT_CARE;
(*next)->transparentGreen = GLX_DONT_CARE;
(*next)->transparentBlue = GLX_DONT_CARE;
(*next)->transparentAlpha = GLX_DONT_CARE;
(*next)->transparentIndex = GLX_DONT_CARE;
(*next)->xRenderable = GLX_DONT_CARE;
(*next)->fbconfigID = GLX_DONT_CARE;
(*next)->swapMethod = GLX_SWAP_UNDEFINED_OML;
(*next)->bindToTextureRgb = GLX_DONT_CARE;
(*next)->bindToTextureRgba = GLX_DONT_CARE;
(*next)->bindToMipmapTexture = GLX_DONT_CARE;
(*next)->bindToTextureTargets = 0;
(*next)->yInverted = GLX_DONT_CARE;
next = & ((*next)->next);
}
return head;
}
__GLcontextModes *
drm_visual_from_config(_EGLConfig *conf)
{
__GLcontextModes *visual;
(void)conf;
visual = drm_visual_modes_create(1, sizeof(*visual));
visual->redBits = 8;
visual->greenBits = 8;
visual->blueBits = 8;
visual->alphaBits = 8;
visual->rgbBits = 32;
visual->doubleBufferMode = 1;
visual->depthBits = 24;
visual->haveDepthBuffer = visual->depthBits > 0;
visual->stencilBits = 8;
visual->haveStencilBuffer = visual->stencilBits > 0;
return visual;
}