diff options
Diffstat (limited to 'src/gallium/state_trackers/egl')
-rw-r--r-- | src/gallium/state_trackers/egl/Makefile | 29 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/egl_context.c | 194 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/egl_surface.c | 418 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/egl_tracker.c | 217 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/egl_tracker.h | 191 | ||||
-rw-r--r-- | src/gallium/state_trackers/egl/egl_visual.c | 85 |
6 files changed, 1134 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile new file mode 100644 index 00000000000..17d1a7a8e40 --- /dev/null +++ b/src/gallium/state_trackers/egl/Makefile @@ -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} diff --git a/src/gallium/state_trackers/egl/egl_context.c b/src/gallium/state_trackers/egl/egl_context.c new file mode 100644 index 00000000000..217fe00338e --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_context.c @@ -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; +} diff --git a/src/gallium/state_trackers/egl/egl_surface.c b/src/gallium/state_trackers/egl/egl_surface.c new file mode 100644 index 00000000000..71292bf2a91 --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_surface.c @@ -0,0 +1,418 @@ + +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "egl_tracker.h" + +#include "egllog.h" + +#include "pipe/p_inlines.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.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); +} + +static void +drm_create_texture(_EGLDriver *drv, + struct drm_screen *scrn, + unsigned w, unsigned h) +{ + struct drm_device *dev = (struct drm_device *)drv; + struct pipe_screen *screen = dev->screen; + struct pipe_surface *surface; + struct pipe_texture *texture; + struct pipe_texture templat; + struct pipe_buffer *buf; + unsigned stride = 1024; + unsigned pitch = 0; + unsigned size = 0; + void *ptr; + + /* ugly */ + if (stride < w) + stride = 2048; + + pitch = stride * 4; + size = h * 2 * pitch; + + buf = pipe_buffer_create(screen, + 0, /* alignment */ + PIPE_BUFFER_USAGE_GPU_READ_WRITE | + PIPE_BUFFER_USAGE_CPU_READ_WRITE, + size); + + if (!buf) + goto err_buf; + +#if DEBUG + ptr = pipe_buffer_map(screen, buf, PIPE_BUFFER_USAGE_CPU_WRITE); + memset(ptr, 0xFF, size); + pipe_buffer_unmap(screen, buf); +#else + (void)ptr; +#endif + + memset(&templat, 0, sizeof(templat)); + templat.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + templat.tex_usage |= PIPE_TEXTURE_USAGE_RENDER_TARGET; + templat.target = PIPE_TEXTURE_2D; + templat.last_level = 0; + templat.depth[0] = 1; + templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templat.width[0] = w; + templat.height[0] = h; + pf_get_block(templat.format, &templat.block); + + texture = screen->texture_blanket(dev->screen, + &templat, + &pitch, + buf); + if (!texture) + goto err_tex; + + surface = screen->get_tex_surface(screen, + texture, + 0, + 0, + 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + + if (!surface) + goto err_surf; + + + scrn->tex = texture; + scrn->surface = surface; + scrn->buffer = buf; + scrn->front.width = w; + scrn->front.height = h; + scrn->front.pitch = pitch; + scrn->front.handle = drm_api_hocks.handle_from_buffer(dev->winsys, scrn->buffer); + if (0) + goto err_handle; + + return; + +err_handle: + pipe_surface_reference(&surface, NULL); +err_surf: + pipe_texture_reference(&texture, NULL); +err_tex: + pipe_buffer_reference(screen, &buf, NULL); +err_buf: + return; +} + +/* + * 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_surface_reference(&screen->surface, NULL); + pipe_texture_reference(&screen->tex, 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); + int ret; + unsigned int i, k; + + if (scrn->shown) + drm_takedown_shown_screen(drv, scrn); + + + drm_create_texture(drv, scrn, mode->Width, mode->Height); + if (!scrn->buffer) + return EGL_FALSE; + + ret = drmModeAddFB(dev->drmFD, + scrn->front.width, scrn->front.height, + 32, 32, scrn->front.pitch, + scrn->front.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_surface_reference(&scrn->surface, NULL); + pipe_texture_reference(&scrn->tex, NULL); + 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) { + surf->user->pipe->flush(surf->user->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL); + surf->user->pipe->surface_copy(surf->user->pipe, + 0, + surf->screen->surface, + 0, 0, + back_surf, + 0, 0, + surf->w, surf->h); + surf->user->pipe->flush(surf->user->pipe, PIPE_FLUSH_RENDER_CACHE | PIPE_FLUSH_TEXTURE_CACHE, NULL); + /* TODO stuff here */ + } + + st_notify_swapbuffers_complete(surf->stfb); + } + + return EGL_TRUE; +} diff --git a/src/gallium/state_trackers/egl/egl_tracker.c b/src/gallium/state_trackers/egl/egl_tracker.c new file mode 100644 index 00000000000..3ca5acb68bf --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_tracker.c @@ -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; +} diff --git a/src/gallium/state_trackers/egl/egl_tracker.h b/src/gallium/state_trackers/egl/egl_tracker.h new file mode 100644 index 00000000000..0b4dd9797d5 --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_tracker.h @@ -0,0 +1,191 @@ + +#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; + struct pipe_texture *tex; + struct pipe_surface *surface; + + /* + * drm + */ + + struct { + unsigned height; + unsigned width; + unsigned pitch; + unsigned handle; + } front; + + /* 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 diff --git a/src/gallium/state_trackers/egl/egl_visual.c b/src/gallium/state_trackers/egl/egl_visual.c new file mode 100644 index 00000000000..e59f893851e --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_visual.c @@ -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; +} |