diff options
author | Dave Airlie <[email protected]> | 2009-02-13 01:11:25 +1000 |
---|---|---|
committer | Dave Airlie <[email protected]> | 2009-02-13 01:11:25 +1000 |
commit | 53116910b10e3b8a05f42970eff311c21808699f (patch) | |
tree | 6831e50a56a02fed324f8cb119e05d837e00d7cf /src/gallium/state_trackers | |
parent | 7e104f9cde94279a902b408e8d1cf21779b393a8 (diff) | |
parent | 0ccbc3c905f0594a35d72887a1f115e148aaa596 (diff) |
Merge remote branch 'origin/master' into radeon-rewrite
Conflicts:
configure.ac
src/mesa/drivers/dri/r200/r200_context.c
src/mesa/drivers/dri/r300/r300_render.c
Diffstat (limited to 'src/gallium/state_trackers')
97 files changed, 22181 insertions, 0 deletions
diff --git a/src/gallium/state_trackers/Makefile b/src/gallium/state_trackers/Makefile new file mode 100644 index 00000000000..265ca468c2d --- /dev/null +++ b/src/gallium/state_trackers/Makefile @@ -0,0 +1,25 @@ +TOP = ../../.. +include $(TOP)/configs/current + + +SUBDIRS = $(GALLIUM_STATE_TRACKERS_DIRS) + + +default: subdirs + + +subdirs: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE)) || exit 1 ; \ + fi \ + done + + +clean: + rm -f `find . -name \*.[oa]` + rm -f `find . -name depend` + + +# Dummy install target +install: diff --git a/src/gallium/state_trackers/README b/src/gallium/state_trackers/README new file mode 100644 index 00000000000..28dd27bbd50 --- /dev/null +++ b/src/gallium/state_trackers/README @@ -0,0 +1,2 @@ +This directory is a placeholder for incubating state-trackers. Mesa's +state-tracker is in src/mesa. diff --git a/src/gallium/state_trackers/egl/Makefile b/src/gallium/state_trackers/egl/Makefile new file mode 100644 index 00000000000..c9124b1c90e --- /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 \ + -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 \ + $(shell pkg-config --cflags pixman-1 xorg-server) \ + ${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..8564972b91e --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_context.c @@ -0,0 +1,193 @@ + +#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 "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..091d437d81b --- /dev/null +++ b/src/gallium/state_trackers/egl/egl_surface.c @@ -0,0 +1,409 @@ + +#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; + + /* 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; + + 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); + struct pipe_context *pipe; + _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; + + st_get_framebuffer_surface(surf->stfb, ST_SURFACE_BACK_LEFT, &back_surf); + + 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..dec82c3a002 --- /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/internal/p_winsys_screen.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; +} diff --git a/src/gallium/state_trackers/g3dvl/Makefile b/src/gallium/state_trackers/g3dvl/Makefile new file mode 100644 index 00000000000..cddfca54fe5 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/Makefile @@ -0,0 +1,21 @@ +TARGET = libg3dvl.a +OBJECTS = vl_display.o vl_screen.o vl_context.o vl_surface.o vl_shader_build.o vl_util.o vl_basic_csc.o \ + vl_r16snorm_mc_buf.o +GALLIUMDIR = ../.. + +CFLAGS += -g -Wall -Werror=implicit-function-declaration -fPIC \ + -I${GALLIUMDIR}/include \ + -I${GALLIUMDIR}/auxiliary \ + -I${GALLIUMDIR}/winsys/g3dvl \ + +############################################# + +.PHONY = all clean + +all: ${TARGET} + +${TARGET}: ${OBJECTS} + ar rcs $@ $^ + +clean: + rm -rf ${OBJECTS} ${TARGET} diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.c b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c new file mode 100644 index 00000000000..187a13a5605 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.c @@ -0,0 +1,715 @@ +#define VL_INTERNAL +#include "vl_basic_csc.h" +#include <assert.h> +#include <pipe/p_context.h> +#include <pipe/p_state.h> +#include <pipe/p_inlines.h> +#include <tgsi/tgsi_parse.h> +#include <tgsi/tgsi_build.h> +#include <util/u_memory.h> +#include "vl_csc.h" +#include "vl_surface.h" +#include "vl_shader_build.h" +#include "vl_types.h" + +struct vlVertexShaderConsts +{ + struct vlVertex4f dst_scale; + struct vlVertex4f dst_trans; + struct vlVertex4f src_scale; + struct vlVertex4f src_trans; +}; + +struct vlFragmentShaderConsts +{ + struct vlVertex4f bias; + float matrix[16]; +}; + +struct vlBasicCSC +{ + struct vlCSC base; + + struct pipe_context *pipe; + struct pipe_viewport_state viewport; + struct pipe_framebuffer_state framebuffer; + struct pipe_texture *framebuffer_tex; + void *sampler; + void *vertex_shader, *fragment_shader; + struct pipe_vertex_buffer vertex_bufs[2]; + struct pipe_vertex_element vertex_elems[2]; + struct pipe_constant_buffer vs_const_buf, fs_const_buf; +}; + +static int vlResizeFrameBuffer +( + struct vlCSC *csc, + unsigned int width, + unsigned int height +) +{ + struct vlBasicCSC *basic_csc; + struct pipe_context *pipe; + struct pipe_texture template; + + assert(csc); + + basic_csc = (struct vlBasicCSC*)csc; + pipe = basic_csc->pipe; + + if (basic_csc->framebuffer.width == width && basic_csc->framebuffer.height == height) + return 0; + + basic_csc->viewport.scale[0] = width; + basic_csc->viewport.scale[1] = height; + basic_csc->viewport.scale[2] = 1; + basic_csc->viewport.scale[3] = 1; + basic_csc->viewport.translate[0] = 0; + basic_csc->viewport.translate[1] = 0; + basic_csc->viewport.translate[2] = 0; + basic_csc->viewport.translate[3] = 0; + + if (basic_csc->framebuffer_tex) + { + pipe_surface_reference(&basic_csc->framebuffer.cbufs[0], NULL); + pipe_texture_reference(&basic_csc->framebuffer_tex, NULL); + } + + memset(&template, 0, sizeof(struct pipe_texture)); + template.target = PIPE_TEXTURE_2D; + template.format = PIPE_FORMAT_A8R8G8B8_UNORM; + template.last_level = 0; + template.width[0] = width; + template.height[0] = height; + template.depth[0] = 1; + template.compressed = 0; + pf_get_block(template.format, &template.block); + template.tex_usage = PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + + basic_csc->framebuffer_tex = pipe->screen->texture_create(pipe->screen, &template); + + basic_csc->framebuffer.width = width; + basic_csc->framebuffer.height = height; + basic_csc->framebuffer.cbufs[0] = pipe->screen->get_tex_surface + ( + pipe->screen, + basic_csc->framebuffer_tex, + 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE + ); + + /* Clear to black, in case video doesn't fill the entire window */ + pipe->clear(pipe, basic_csc->framebuffer.cbufs[0], 0); + + return 0; +} + +static int vlBegin +( + struct vlCSC *csc +) +{ + struct vlBasicCSC *basic_csc; + struct pipe_context *pipe; + + assert(csc); + + basic_csc = (struct vlBasicCSC*)csc; + pipe = basic_csc->pipe; + + pipe->set_framebuffer_state(pipe, &basic_csc->framebuffer); + pipe->set_viewport_state(pipe, &basic_csc->viewport); + pipe->bind_sampler_states(pipe, 1, (void**)&basic_csc->sampler); + /* Source texture set in vlPutPictureCSC() */ + pipe->bind_vs_state(pipe, basic_csc->vertex_shader); + pipe->bind_fs_state(pipe, basic_csc->fragment_shader); + pipe->set_vertex_buffers(pipe, 2, basic_csc->vertex_bufs); + pipe->set_vertex_elements(pipe, 2, basic_csc->vertex_elems); + pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &basic_csc->vs_const_buf); + pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &basic_csc->fs_const_buf); + + return 0; +} + +static int vlPutPictureCSC +( + struct vlCSC *csc, + struct vlSurface *surface, + int srcx, + int srcy, + int srcw, + int srch, + int destx, + int desty, + int destw, + int desth, + enum vlPictureType picture_type +) +{ + struct vlBasicCSC *basic_csc; + struct pipe_context *pipe; + struct vlVertexShaderConsts *vs_consts; + + assert(csc); + assert(surface); + + basic_csc = (struct vlBasicCSC*)csc; + pipe = basic_csc->pipe; + + vs_consts = pipe_buffer_map + ( + pipe->screen, + basic_csc->vs_const_buf.buffer, + PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD + ); + + vs_consts->dst_scale.x = destw / (float)basic_csc->framebuffer.cbufs[0]->width; + vs_consts->dst_scale.y = desth / (float)basic_csc->framebuffer.cbufs[0]->height; + vs_consts->dst_scale.z = 1; + vs_consts->dst_scale.w = 1; + vs_consts->dst_trans.x = destx / (float)basic_csc->framebuffer.cbufs[0]->width; + vs_consts->dst_trans.y = desty / (float)basic_csc->framebuffer.cbufs[0]->height; + vs_consts->dst_trans.z = 0; + vs_consts->dst_trans.w = 0; + + vs_consts->src_scale.x = srcw / (float)surface->texture->width[0]; + vs_consts->src_scale.y = srch / (float)surface->texture->height[0]; + vs_consts->src_scale.z = 1; + vs_consts->src_scale.w = 1; + vs_consts->src_trans.x = srcx / (float)surface->texture->width[0]; + vs_consts->src_trans.y = srcy / (float)surface->texture->height[0]; + vs_consts->src_trans.z = 0; + vs_consts->src_trans.w = 0; + + pipe_buffer_unmap(pipe->screen, basic_csc->vs_const_buf.buffer); + + pipe->set_sampler_textures(pipe, 1, &surface->texture); + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLE_STRIP, 0, 4); + + return 0; +} + +static int vlEnd +( + struct vlCSC *csc +) +{ + assert(csc); + + return 0; +} + +static struct pipe_surface* vlGetFrameBuffer +( + struct vlCSC *csc +) +{ + struct vlBasicCSC *basic_csc; + + assert(csc); + + basic_csc = (struct vlBasicCSC*)csc; + + return basic_csc->framebuffer.cbufs[0]; +} + +static int vlDestroy +( + struct vlCSC *csc +) +{ + struct vlBasicCSC *basic_csc; + struct pipe_context *pipe; + unsigned int i; + + assert(csc); + + basic_csc = (struct vlBasicCSC*)csc; + pipe = basic_csc->pipe; + + if (basic_csc->framebuffer_tex) + { + pipe_surface_reference(&basic_csc->framebuffer.cbufs[0], NULL); + pipe_texture_reference(&basic_csc->framebuffer_tex, NULL); + } + + pipe->delete_sampler_state(pipe, basic_csc->sampler); + pipe->delete_vs_state(pipe, basic_csc->vertex_shader); + pipe->delete_fs_state(pipe, basic_csc->fragment_shader); + + for (i = 0; i < 2; ++i) + pipe_buffer_reference(pipe->screen, &basic_csc->vertex_bufs[i].buffer, NULL); + + pipe_buffer_reference(pipe->screen, &basic_csc->vs_const_buf.buffer, NULL); + pipe_buffer_reference(pipe->screen, &basic_csc->fs_const_buf.buffer, NULL); + + FREE(basic_csc); + + return 0; +} + +/* + * Represents 2 triangles in a strip in normalized coords. + * Used to render the surface onto the frame buffer. + */ +static const struct vlVertex2f surface_verts[4] = +{ + {0.0f, 0.0f}, + {0.0f, 1.0f}, + {1.0f, 0.0f}, + {1.0f, 1.0f} +}; + +/* + * Represents texcoords for the above. We can use the position values directly. + * TODO: Duplicate these in the shader, no need to create a buffer. + */ +static const struct vlVertex2f *surface_texcoords = surface_verts; + +/* + * Identity color conversion constants, for debugging + */ +static const struct vlFragmentShaderConsts identity = +{ + { + 0.0f, 0.0f, 0.0f, 0.0f + }, + { + 1.0f, 0.0f, 0.0f, 0.0f, + 0.0f, 1.0f, 0.0f, 0.0f, + 0.0f, 0.0f, 1.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + } +}; + +/* + * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [16,235] + */ +static const struct vlFragmentShaderConsts bt_601 = +{ + { + 0.0f, 0.501960784f, 0.501960784f, 0.0f + }, + { + 1.0f, 0.0f, 1.371f, 0.0f, + 1.0f, -0.336f, -0.698f, 0.0f, + 1.0f, 1.732f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + } +}; + +/* + * Converts ITU-R BT.601 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [0,255] + */ +static const struct vlFragmentShaderConsts bt_601_full = +{ + { + 0.062745098f, 0.501960784f, 0.501960784f, 0.0f + }, + { + 1.164f, 0.0f, 1.596f, 0.0f, + 1.164f, -0.391f, -0.813f, 0.0f, + 1.164f, 2.018f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + } +}; + +/* + * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [16,235] + */ +static const struct vlFragmentShaderConsts bt_709 = +{ + { + 0.0f, 0.501960784f, 0.501960784f, 0.0f + }, + { + 1.0f, 0.0f, 1.540f, 0.0f, + 1.0f, -0.183f, -0.459f, 0.0f, + 1.0f, 1.816f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + } +}; + +/* + * Converts ITU-R BT.709 YCbCr pixels to RGB pixels where: + * Y is in [16,235], Cb and Cr are in [16,240] + * R, G, and B are in [0,255] + */ +const struct vlFragmentShaderConsts bt_709_full = +{ + { + 0.062745098f, 0.501960784f, 0.501960784f, 0.0f + }, + { + 1.164f, 0.0f, 1.793f, 0.0f, + 1.164f, -0.213f, -0.534f, 0.0f, + 1.164f, 2.115f, 0.0f, 0.0f, + 0.0f, 0.0f, 0.0f, 1.0f + } +}; + +static int vlCreateVertexShader +( + struct vlBasicCSC *csc +) +{ + const unsigned int max_tokens = 50; + + struct pipe_context *pipe; + struct pipe_shader_state vs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(context); + + pipe = csc->pipe; + tokens = (struct tgsi_token*)MALLOC(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + + ti = 3; + + /* + * decl i0 ; Vertex pos + * decl i1 ; Vertex texcoords + */ + for (i = 0; i < 2; i++) + { + decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * decl c0 ; Scaling vector to scale vertex pos rect to destination size + * decl c1 ; Translation vector to move vertex pos rect into position + * decl c2 ; Scaling vector to scale texcoord rect to source size + * decl c3 ; Translation vector to move texcoord rect into position + */ + decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 3); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * decl o0 ; Vertex pos + * decl o1 ; Vertex texcoords + */ + for (i = 0; i < 2; i++) + { + decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* decl t0, t1 */ + decl = vl_decl_temps(0, 1); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * madd o0, i0, c0, c1 ; Scale and translate unit output rect to destination size and pos + * madd o1, i1, c2, c3 ; Scale and translate unit texcoord rect to source size and pos + */ + for (i = 0; i < 2; ++i) + { + inst = vl_inst4(TGSI_OPCODE_MADD, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i, TGSI_FILE_CONSTANT, i * 2, TGSI_FILE_CONSTANT, i * 2 + 1); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + vs.tokens = tokens; + csc->vertex_shader = pipe->create_vs_state(pipe, &vs); + FREE(tokens); + + return 0; +} + +static int vlCreateFragmentShader +( + struct vlBasicCSC *csc +) +{ + const unsigned int max_tokens = 50; + + struct pipe_context *pipe; + struct pipe_shader_state fs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(context); + + pipe = csc->pipe; + tokens = (struct tgsi_token*)MALLOC(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + + ti = 3; + + /* decl i0 ; Texcoords for s0 */ + decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, 1, 0, 0, TGSI_INTERPOLATE_LINEAR); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * decl c0 ; Bias vector for CSC + * decl c1-c4 ; CSC matrix c1-c4 + */ + decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 4); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl o0 ; Fragment color */ + decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl t0 */ + decl = vl_decl_temps(0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl s0 ; Sampler for tex containing picture to display */ + decl = vl_decl_samplers(0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* tex2d t0, i0, s0 ; Read src pixel */ + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_INPUT, 0, TGSI_FILE_SAMPLER, 0); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* sub t0, t0, c0 ; Subtract bias vector from pixel */ + inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* + * dp4 o0.x, t0, c1 ; Multiply pixel by the color conversion matrix + * dp4 o0.y, t0, c2 + * dp4 o0.z, t0, c3 + */ + for (i = 0; i < 3; ++i) + { + inst = vl_inst3(TGSI_OPCODE_DP4, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, i + 1); + inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + fs.tokens = tokens; + csc->fragment_shader = pipe->create_fs_state(pipe, &fs); + FREE(tokens); + + return 0; +} + +static int vlCreateDataBufs +( + struct vlBasicCSC *csc +) +{ + struct pipe_context *pipe; + + assert(csc); + + pipe = csc->pipe; + + /* + * Create our vertex buffer and vertex buffer element + * VB contains 4 vertices that render a quad covering the entire window + * to display a rendered surface + * Quad is rendered as a tri strip + */ + csc->vertex_bufs[0].stride = sizeof(struct vlVertex2f); + csc->vertex_bufs[0].max_index = 3; + csc->vertex_bufs[0].buffer_offset = 0; + csc->vertex_bufs[0].buffer = pipe_buffer_create + ( + pipe->screen, + 1, + PIPE_BUFFER_USAGE_VERTEX, + sizeof(struct vlVertex2f) * 4 + ); + + memcpy + ( + pipe_buffer_map(pipe->screen, csc->vertex_bufs[0].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), + surface_verts, + sizeof(struct vlVertex2f) * 4 + ); + + pipe_buffer_unmap(pipe->screen, csc->vertex_bufs[0].buffer); + + csc->vertex_elems[0].src_offset = 0; + csc->vertex_elems[0].vertex_buffer_index = 0; + csc->vertex_elems[0].nr_components = 2; + csc->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* + * Create our texcoord buffer and texcoord buffer element + * Texcoord buffer contains the TCs for mapping the rendered surface to the 4 vertices + */ + csc->vertex_bufs[1].stride = sizeof(struct vlVertex2f); + csc->vertex_bufs[1].max_index = 3; + csc->vertex_bufs[1].buffer_offset = 0; + csc->vertex_bufs[1].buffer = pipe_buffer_create + ( + pipe->screen, + 1, + PIPE_BUFFER_USAGE_VERTEX, + sizeof(struct vlVertex2f) * 4 + ); + + memcpy + ( + pipe_buffer_map(pipe->screen, csc->vertex_bufs[1].buffer, PIPE_BUFFER_USAGE_CPU_WRITE), + surface_texcoords, + sizeof(struct vlVertex2f) * 4 + ); + + pipe_buffer_unmap(pipe->screen, csc->vertex_bufs[1].buffer); + + csc->vertex_elems[1].src_offset = 0; + csc->vertex_elems[1].vertex_buffer_index = 1; + csc->vertex_elems[1].nr_components = 2; + csc->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* + * Create our vertex shader's constant buffer + * Const buffer contains scaling and translation vectors + */ + csc->vs_const_buf.buffer = pipe_buffer_create + ( + pipe->screen, + 1, + PIPE_BUFFER_USAGE_CONSTANT | PIPE_BUFFER_USAGE_DISCARD, + sizeof(struct vlVertexShaderConsts) + ); + + /* + * Create our fragment shader's constant buffer + * Const buffer contains the color conversion matrix and bias vectors + */ + csc->fs_const_buf.buffer = pipe_buffer_create + ( + pipe->screen, + 1, + PIPE_BUFFER_USAGE_CONSTANT, + sizeof(struct vlFragmentShaderConsts) + ); + + /* + * TODO: Refactor this into a seperate function, + * allow changing the CSC matrix at runtime to switch between regular & full versions + */ + memcpy + ( + pipe_buffer_map(pipe->screen, csc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), + &bt_601_full, + sizeof(struct vlFragmentShaderConsts) + ); + + pipe_buffer_unmap(pipe->screen, csc->fs_const_buf.buffer); + + return 0; +} + +static int vlInit +( + struct vlBasicCSC *csc +) +{ + struct pipe_context *pipe; + struct pipe_sampler_state sampler; + + assert(csc); + + pipe = csc->pipe; + + /* Delay creating the FB until vlPutPictureCSC() so we know window size */ + csc->framebuffer_tex = NULL; + csc->framebuffer.width = 0; + csc->framebuffer.height = 0; + csc->framebuffer.nr_cbufs = 1; + csc->framebuffer.cbufs[0] = NULL; + csc->framebuffer.zsbuf = NULL; + + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.min_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.mag_img_filter = PIPE_TEX_FILTER_LINEAR; + sampler.compare_mode = PIPE_TEX_COMPARE_NONE; + sampler.compare_func = PIPE_FUNC_ALWAYS; + sampler.normalized_coords = 1; + /*sampler.prefilter = ;*/ + /*sampler.shadow_ambient = ;*/ + /*sampler.lod_bias = ;*/ + /*sampler.min_lod = ;*/ + /*sampler.max_lod = ;*/ + /*sampler.border_color[i] = ;*/ + /*sampler.max_anisotropy = ;*/ + csc->sampler = pipe->create_sampler_state(pipe, &sampler); + + vlCreateVertexShader(csc); + vlCreateFragmentShader(csc); + vlCreateDataBufs(csc); + + return 0; +} + +int vlCreateBasicCSC +( + struct pipe_context *pipe, + struct vlCSC **csc +) +{ + struct vlBasicCSC *basic_csc; + + assert(pipe); + assert(csc); + + basic_csc = CALLOC_STRUCT(vlBasicCSC); + + if (!basic_csc) + return 1; + + basic_csc->base.vlResizeFrameBuffer = &vlResizeFrameBuffer; + basic_csc->base.vlBegin = &vlBegin; + basic_csc->base.vlPutPicture = &vlPutPictureCSC; + basic_csc->base.vlEnd = &vlEnd; + basic_csc->base.vlGetFrameBuffer = &vlGetFrameBuffer; + basic_csc->base.vlDestroy = &vlDestroy; + basic_csc->pipe = pipe; + + vlInit(basic_csc); + + *csc = &basic_csc->base; + + return 0; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_basic_csc.h b/src/gallium/state_trackers/g3dvl/vl_basic_csc.h new file mode 100644 index 00000000000..2e17f1d814a --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_basic_csc.h @@ -0,0 +1,13 @@ +#ifndef vl_basic_csc_h +#define vl_basic_csc_h + +struct pipe_context; +struct vlCSC; + +int vlCreateBasicCSC +( + struct pipe_context *pipe, + struct vlCSC **csc +); + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_context.c b/src/gallium/state_trackers/g3dvl/vl_context.c new file mode 100644 index 00000000000..65ddb9f01ef --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_context.c @@ -0,0 +1,208 @@ +#define VL_INTERNAL +#include "vl_context.h" +#include <assert.h> +#include <pipe/p_context.h> +#include <pipe/p_state.h> +#include <util/u_memory.h> +#include "vl_render.h" +#include "vl_r16snorm_mc_buf.h" +#include "vl_csc.h" +#include "vl_basic_csc.h" + +static int vlInitCommon(struct vlContext *context) +{ + struct pipe_context *pipe; + struct pipe_rasterizer_state rast; + struct pipe_blend_state blend; + struct pipe_depth_stencil_alpha_state dsa; + unsigned int i; + + assert(context); + + pipe = context->pipe; + + rast.flatshade = 1; + rast.flatshade_first = 0; + rast.light_twoside = 0; + rast.front_winding = PIPE_WINDING_CCW; + rast.cull_mode = PIPE_WINDING_CW; + rast.fill_cw = PIPE_POLYGON_MODE_FILL; + rast.fill_ccw = PIPE_POLYGON_MODE_FILL; + rast.offset_cw = 0; + rast.offset_ccw = 0; + rast.scissor = 0; + rast.poly_smooth = 0; + rast.poly_stipple_enable = 0; + rast.point_sprite = 0; + rast.point_size_per_vertex = 0; + rast.multisample = 0; + rast.line_smooth = 0; + rast.line_stipple_enable = 0; + rast.line_stipple_factor = 0; + rast.line_stipple_pattern = 0; + rast.line_last_pixel = 0; + /* Don't need clipping, but viewport mapping done here */ + rast.bypass_clipping = 0; + rast.bypass_vs = 0; + rast.origin_lower_left = 0; + rast.line_width = 1; + rast.point_smooth = 0; + rast.point_size = 1; + rast.offset_units = 1; + rast.offset_scale = 1; + /*rast.sprite_coord_mode[i] = ;*/ + context->raster = pipe->create_rasterizer_state(pipe, &rast); + pipe->bind_rasterizer_state(pipe, context->raster); + + blend.blend_enable = 0; + blend.rgb_func = PIPE_BLEND_ADD; + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_func = PIPE_BLEND_ADD; + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ONE; + blend.logicop_enable = 0; + blend.logicop_func = PIPE_LOGICOP_CLEAR; + /* Needed to allow color writes to FB, even if blending disabled */ + blend.colormask = PIPE_MASK_RGBA; + blend.dither = 0; + context->blend = pipe->create_blend_state(pipe, &blend); + pipe->bind_blend_state(pipe, context->blend); + + dsa.depth.enabled = 0; + dsa.depth.writemask = 0; + dsa.depth.func = PIPE_FUNC_ALWAYS; + dsa.depth.occlusion_count = 0; + for (i = 0; i < 2; ++i) + { + dsa.stencil[i].enabled = 0; + dsa.stencil[i].func = PIPE_FUNC_ALWAYS; + dsa.stencil[i].fail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[i].zpass_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[i].zfail_op = PIPE_STENCIL_OP_KEEP; + dsa.stencil[i].ref_value = 0; + dsa.stencil[i].valuemask = 0; + dsa.stencil[i].writemask = 0; + } + dsa.alpha.enabled = 0; + dsa.alpha.func = PIPE_FUNC_ALWAYS; + dsa.alpha.ref_value = 0; + context->dsa = pipe->create_depth_stencil_alpha_state(pipe, &dsa); + pipe->bind_depth_stencil_alpha_state(pipe, context->dsa); + + return 0; +} + +int vlCreateContext +( + struct vlScreen *screen, + struct pipe_context *pipe, + unsigned int picture_width, + unsigned int picture_height, + enum vlFormat picture_format, + enum vlProfile profile, + enum vlEntryPoint entry_point, + struct vlContext **context +) +{ + struct vlContext *ctx; + + assert(screen); + assert(context); + assert(pipe); + + ctx = CALLOC_STRUCT(vlContext); + + if (!ctx) + return 1; + + ctx->screen = screen; + ctx->pipe = pipe; + ctx->picture_width = picture_width; + ctx->picture_height = picture_height; + ctx->picture_format = picture_format; + ctx->profile = profile; + ctx->entry_point = entry_point; + + vlInitCommon(ctx); + + vlCreateR16SNormBufferedMC(pipe, picture_width, picture_height, picture_format, &ctx->render); + vlCreateBasicCSC(pipe, &ctx->csc); + + *context = ctx; + + return 0; +} + +int vlDestroyContext +( + struct vlContext *context +) +{ + assert(context); + + /* XXX: Must unbind shaders before we can delete them for some reason */ + context->pipe->bind_vs_state(context->pipe, NULL); + context->pipe->bind_fs_state(context->pipe, NULL); + + context->render->vlDestroy(context->render); + context->csc->vlDestroy(context->csc); + + context->pipe->delete_blend_state(context->pipe, context->blend); + context->pipe->delete_rasterizer_state(context->pipe, context->raster); + context->pipe->delete_depth_stencil_alpha_state(context->pipe, context->dsa); + + FREE(context); + + return 0; +} + +struct vlScreen* vlContextGetScreen +( + struct vlContext *context +) +{ + assert(context); + + return context->screen; +} + +struct pipe_context* vlGetPipeContext +( + struct vlContext *context +) +{ + assert(context); + + return context->pipe; +} + +unsigned int vlGetPictureWidth +( + struct vlContext *context +) +{ + assert(context); + + return context->picture_width; +} + +unsigned int vlGetPictureHeight +( + struct vlContext *context +) +{ + assert(context); + + return context->picture_height; +} + +enum vlFormat vlGetPictureFormat +( + struct vlContext *context +) +{ + assert(context); + + return context->picture_format; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_context.h b/src/gallium/state_trackers/g3dvl/vl_context.h new file mode 100644 index 00000000000..3d14634c44e --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_context.h @@ -0,0 +1,73 @@ +#ifndef vl_context_h +#define vl_context_h + +#include "vl_types.h" + +struct pipe_context; + +#ifdef VL_INTERNAL +struct vlRender; +struct vlCSC; + +struct vlContext +{ + struct vlScreen *screen; + struct pipe_context *pipe; + unsigned int picture_width; + unsigned int picture_height; + enum vlFormat picture_format; + enum vlProfile profile; + enum vlEntryPoint entry_point; + + void *raster; + void *dsa; + void *blend; + + struct vlRender *render; + struct vlCSC *csc; +}; +#endif + +int vlCreateContext +( + struct vlScreen *screen, + struct pipe_context *pipe, + unsigned int picture_width, + unsigned int picture_height, + enum vlFormat picture_format, + enum vlProfile profile, + enum vlEntryPoint entry_point, + struct vlContext **context +); + +int vlDestroyContext +( + struct vlContext *context +); + +struct vlScreen* vlContextGetScreen +( + struct vlContext *context +); + +struct pipe_context* vlGetPipeContext +( + struct vlContext *context +); + +unsigned int vlGetPictureWidth +( + struct vlContext *context +); + +unsigned int vlGetPictureHeight +( + struct vlContext *context +); + +enum vlFormat vlGetPictureFormat +( + struct vlContext *context +); + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_csc.h b/src/gallium/state_trackers/g3dvl/vl_csc.h new file mode 100644 index 00000000000..36417a27929 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_csc.h @@ -0,0 +1,53 @@ +#ifndef vl_csc_h +#define vl_csc_h + +#include "vl_types.h" + +struct pipe_surface; + +struct vlCSC +{ + int (*vlResizeFrameBuffer) + ( + struct vlCSC *csc, + unsigned int width, + unsigned int height + ); + + int (*vlBegin) + ( + struct vlCSC *csc + ); + + int (*vlPutPicture) + ( + struct vlCSC *csc, + struct vlSurface *surface, + int srcx, + int srcy, + int srcw, + int srch, + int destx, + int desty, + int destw, + int desth, + enum vlPictureType picture_type + ); + + int (*vlEnd) + ( + struct vlCSC *csc + ); + + struct pipe_surface* (*vlGetFrameBuffer) + ( + struct vlCSC *csc + ); + + int (*vlDestroy) + ( + struct vlCSC *csc + ); +}; + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_defs.h b/src/gallium/state_trackers/g3dvl/vl_defs.h new file mode 100644 index 00000000000..d612d02502f --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_defs.h @@ -0,0 +1,11 @@ +#ifndef vl_defs_h +#define vl_defs_h + +#define VL_BLOCK_WIDTH 8 +#define VL_BLOCK_HEIGHT 8 +#define VL_BLOCK_SIZE (VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT) +#define VL_MACROBLOCK_WIDTH 16 +#define VL_MACROBLOCK_HEIGHT 16 +#define VL_MACROBLOCK_SIZE (VL_MACROBLOCK_WIDTH * VL_MACROBLOCK_HEIGHT) + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_display.c b/src/gallium/state_trackers/g3dvl/vl_display.c new file mode 100644 index 00000000000..dce06de7583 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_display.c @@ -0,0 +1,48 @@ +#define VL_INTERNAL +#include "vl_display.h" +#include <assert.h> +#include <util/u_memory.h> + +int vlCreateDisplay +( + vlNativeDisplay native_display, + struct vlDisplay **display +) +{ + struct vlDisplay *dpy; + + assert(native_display); + assert(display); + + dpy = CALLOC_STRUCT(vlDisplay); + + if (!dpy) + return 1; + + dpy->native = native_display; + *display = dpy; + + return 0; +} + +int vlDestroyDisplay +( + struct vlDisplay *display +) +{ + assert(display); + + FREE(display); + + return 0; +} + +vlNativeDisplay vlGetNativeDisplay +( + struct vlDisplay *display +) +{ + assert(display); + + return display->native; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_display.h b/src/gallium/state_trackers/g3dvl/vl_display.h new file mode 100644 index 00000000000..e11fd407993 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_display.h @@ -0,0 +1,29 @@ +#ifndef vl_display_h +#define vl_display_h + +#include "vl_types.h" + +#ifdef VL_INTERNAL +struct vlDisplay +{ + vlNativeDisplay native; +}; +#endif + +int vlCreateDisplay +( + vlNativeDisplay native_display, + struct vlDisplay **display +); + +int vlDestroyDisplay +( + struct vlDisplay *display +); + +vlNativeDisplay vlGetNativeDisplay +( + struct vlDisplay *display +); + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c new file mode 100644 index 00000000000..2176bb86d8a --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.c @@ -0,0 +1,1155 @@ +#define VL_INTERNAL +#include "vl_r16snorm_mc_buf.h" +#include <assert.h> +#include <pipe/p_context.h> +#include <pipe/p_screen.h> +#include <pipe/p_state.h> +#include <pipe/p_inlines.h> +#include <tgsi/tgsi_parse.h> +#include <tgsi/tgsi_build.h> +#include <util/u_math.h> +#include <util/u_memory.h> +#include "vl_render.h" +#include "vl_shader_build.h" +#include "vl_surface.h" +#include "vl_util.h" +#include "vl_types.h" +#include "vl_defs.h" + +const unsigned int DEFAULT_BUF_ALIGNMENT = 1; + +enum vlMacroBlockTypeEx +{ + vlMacroBlockExTypeIntra, + vlMacroBlockExTypeFwdPredictedFrame, + vlMacroBlockExTypeFwdPredictedField, + vlMacroBlockExTypeBkwdPredictedFrame, + vlMacroBlockExTypeBkwdPredictedField, + vlMacroBlockExTypeBiPredictedFrame, + vlMacroBlockExTypeBiPredictedField, + + vlNumMacroBlockExTypes +}; + +struct vlVertexShaderConsts +{ + struct vlVertex4f denorm; +}; + +struct vlFragmentShaderConsts +{ + struct vlVertex4f multiplier; + struct vlVertex4f div; +}; + +struct vlMacroBlockVertexStream0 +{ + struct vlVertex2f pos; + struct vlVertex2f luma_tc; + struct vlVertex2f cb_tc; + struct vlVertex2f cr_tc; +}; + +struct vlR16SnormBufferedMC +{ + struct vlRender base; + + unsigned int picture_width; + unsigned int picture_height; + enum vlFormat picture_format; + unsigned int macroblocks_per_picture; + + struct vlSurface *buffered_surface; + struct vlSurface *past_surface; + struct vlSurface *future_surface; + struct vlVertex2f surface_tex_inv_size; + struct vlVertex2f zero_block[3]; + unsigned int num_macroblocks; + struct vlMpeg2MacroBlock *macroblocks; + struct pipe_surface *tex_surface[3]; + short *texels[3]; + + struct pipe_context *pipe; + struct pipe_viewport_state viewport; + struct pipe_framebuffer_state render_target; + + union + { + void *all[5]; + struct + { + void *y; + void *cb; + void *cr; + void *ref[2]; + }; + } samplers; + + union + { + struct pipe_texture *all[5]; + struct + { + struct pipe_texture *y; + struct pipe_texture *cb; + struct pipe_texture *cr; + struct pipe_texture *ref[2]; + }; + } textures; + + union + { + struct pipe_vertex_buffer all[3]; + struct + { + struct pipe_vertex_buffer ycbcr; + struct pipe_vertex_buffer ref[2]; + }; + } vertex_bufs; + + void *i_vs, *p_vs[2], *b_vs[2]; + void *i_fs, *p_fs[2], *b_fs[2]; + struct pipe_vertex_element vertex_elems[8]; + struct pipe_constant_buffer vs_const_buf; + struct pipe_constant_buffer fs_const_buf; +}; + +static inline int vlBegin +( + struct vlRender *render +) +{ + assert(render); + + return 0; +} + +static inline int vlGrabFrameCodedBlock(short *src, short *dst, unsigned int dst_pitch) +{ + unsigned int y; + + for (y = 0; y < VL_BLOCK_HEIGHT; ++y) + memcpy + ( + dst + y * dst_pitch, + src + y * VL_BLOCK_WIDTH, + VL_BLOCK_WIDTH * 2 + ); + + return 0; +} + +static inline int vlGrabFieldCodedBlock(short *src, short *dst, unsigned int dst_pitch) +{ + unsigned int y; + + for (y = 0; y < VL_BLOCK_HEIGHT; ++y) + memcpy + ( + dst + y * dst_pitch * 2, + src + y * VL_BLOCK_WIDTH, + VL_BLOCK_WIDTH * 2 + ); + + return 0; +} + +static inline int vlGrabNoBlock(short *dst, unsigned int dst_pitch) +{ + unsigned int y; + + for (y = 0; y < VL_BLOCK_HEIGHT; ++y) + memset + ( + dst + y * dst_pitch, + 0, + VL_BLOCK_WIDTH * 2 + ); + + return 0; +} + +static inline int vlGrabBlocks +( + struct vlR16SnormBufferedMC *mc, + unsigned int mbx, + unsigned int mby, + enum vlDCTType dct_type, + unsigned int coded_block_pattern, + short *blocks +) +{ + short *texels; + unsigned int tex_pitch; + unsigned int x, y, tb = 0, sb = 0; + unsigned int mbpx = mbx * VL_MACROBLOCK_WIDTH, mbpy = mby * VL_MACROBLOCK_HEIGHT; + + assert(mc); + assert(blocks); + + tex_pitch = mc->tex_surface[0]->stride / mc->tex_surface[0]->block.size; + texels = mc->texels[0] + mbpy * tex_pitch + mbpx; + + for (y = 0; y < 2; ++y) + { + for (x = 0; x < 2; ++x, ++tb) + { + if ((coded_block_pattern >> (5 - tb)) & 1) + { + short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; + + if (dct_type == vlDCTTypeFrameCoded) + { + vlGrabFrameCodedBlock + ( + cur_block, + texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH, + tex_pitch + ); + } + else + { + vlGrabFieldCodedBlock + ( + cur_block, + texels + y * tex_pitch + x * VL_BLOCK_WIDTH, + tex_pitch + ); + } + + ++sb; + } + else if (mc->zero_block[0].x < 0.0f) + { + vlGrabNoBlock(texels + y * tex_pitch * VL_BLOCK_HEIGHT + x * VL_BLOCK_WIDTH, tex_pitch); + + mc->zero_block[0].x = (mbpx + x * 8) * mc->surface_tex_inv_size.x; + mc->zero_block[0].y = (mbpy + y * 8) * mc->surface_tex_inv_size.y; + } + } + } + + /* TODO: Implement 422, 444 */ + mbpx >>= 1; + mbpy >>= 1; + + for (tb = 0; tb < 2; ++tb) + { + tex_pitch = mc->tex_surface[tb + 1]->stride / mc->tex_surface[tb + 1]->block.size; + texels = mc->texels[tb + 1] + mbpy * tex_pitch + mbpx; + + if ((coded_block_pattern >> (1 - tb)) & 1) + { + short *cur_block = blocks + sb * VL_BLOCK_WIDTH * VL_BLOCK_HEIGHT; + + vlGrabFrameCodedBlock + ( + cur_block, + texels, + tex_pitch + ); + + ++sb; + } + else if (mc->zero_block[tb + 1].x < 0.0f) + { + vlGrabNoBlock(texels, tex_pitch); + + mc->zero_block[tb + 1].x = (mbpx << 1) * mc->surface_tex_inv_size.x; + mc->zero_block[tb + 1].y = (mbpy << 1) * mc->surface_tex_inv_size.y; + } + } + + return 0; +} + +static inline enum vlMacroBlockTypeEx vlGetMacroBlockTypeEx(struct vlMpeg2MacroBlock *mb) +{ + assert(mb); + + switch (mb->mb_type) + { + case vlMacroBlockTypeIntra: + return vlMacroBlockExTypeIntra; + case vlMacroBlockTypeFwdPredicted: + return mb->mo_type == vlMotionTypeFrame ? + vlMacroBlockExTypeFwdPredictedFrame : vlMacroBlockExTypeFwdPredictedField; + case vlMacroBlockTypeBkwdPredicted: + return mb->mo_type == vlMotionTypeFrame ? + vlMacroBlockExTypeBkwdPredictedFrame : vlMacroBlockExTypeBkwdPredictedField; + case vlMacroBlockTypeBiPredicted: + return mb->mo_type == vlMotionTypeFrame ? + vlMacroBlockExTypeBiPredictedFrame : vlMacroBlockExTypeBiPredictedField; + default: + assert(0); + } + + /* Unreachable */ + return -1; +} + +static inline int vlGrabMacroBlock +( + struct vlR16SnormBufferedMC *mc, + struct vlMpeg2MacroBlock *macroblock +) +{ + assert(mc); + assert(macroblock); + assert(mc->num_macroblocks < mc->macroblocks_per_picture); + + mc->macroblocks[mc->num_macroblocks].mbx = macroblock->mbx; + mc->macroblocks[mc->num_macroblocks].mby = macroblock->mby; + mc->macroblocks[mc->num_macroblocks].mb_type = macroblock->mb_type; + mc->macroblocks[mc->num_macroblocks].mo_type = macroblock->mo_type; + mc->macroblocks[mc->num_macroblocks].dct_type = macroblock->dct_type; + mc->macroblocks[mc->num_macroblocks].PMV[0][0][0] = macroblock->PMV[0][0][0]; + mc->macroblocks[mc->num_macroblocks].PMV[0][0][1] = macroblock->PMV[0][0][1]; + mc->macroblocks[mc->num_macroblocks].PMV[0][1][0] = macroblock->PMV[0][1][0]; + mc->macroblocks[mc->num_macroblocks].PMV[0][1][1] = macroblock->PMV[0][1][1]; + mc->macroblocks[mc->num_macroblocks].PMV[1][0][0] = macroblock->PMV[1][0][0]; + mc->macroblocks[mc->num_macroblocks].PMV[1][0][1] = macroblock->PMV[1][0][1]; + mc->macroblocks[mc->num_macroblocks].PMV[1][1][0] = macroblock->PMV[1][1][0]; + mc->macroblocks[mc->num_macroblocks].PMV[1][1][1] = macroblock->PMV[1][1][1]; + mc->macroblocks[mc->num_macroblocks].cbp = macroblock->cbp; + mc->macroblocks[mc->num_macroblocks].blocks = macroblock->blocks; + + vlGrabBlocks + ( + mc, + macroblock->mbx, + macroblock->mby, + macroblock->dct_type, + macroblock->cbp, + macroblock->blocks + ); + + mc->num_macroblocks++; + + return 0; +} + +#define SET_BLOCK(vb, cbp, mbx, mby, unitx, unity, ofsx, ofsy, hx, hy, lm, cbm, crm, zb) \ + do { \ + (vb)[0].pos.x = (mbx) * (unitx) + (ofsx); (vb)[0].pos.y = (mby) * (unity) + (ofsy); \ + (vb)[1].pos.x = (mbx) * (unitx) + (ofsx); (vb)[1].pos.y = (mby) * (unity) + (ofsy) + (hy); \ + (vb)[2].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].pos.y = (mby) * (unity) + (ofsy); \ + (vb)[3].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].pos.y = (mby) * (unity) + (ofsy); \ + (vb)[4].pos.x = (mbx) * (unitx) + (ofsx); (vb)[4].pos.y = (mby) * (unity) + (ofsy) + (hy); \ + (vb)[5].pos.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].pos.y = (mby) * (unity) + (ofsy) + (hy); \ + \ + if ((cbp) & (lm)) \ + { \ + (vb)[0].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].luma_tc.y = (mby) * (unity) + (ofsy); \ + (vb)[1].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \ + (vb)[2].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].luma_tc.y = (mby) * (unity) + (ofsy); \ + (vb)[3].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].luma_tc.y = (mby) * (unity) + (ofsy); \ + (vb)[4].luma_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \ + (vb)[5].luma_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].luma_tc.y = (mby) * (unity) + (ofsy) + (hy); \ + } \ + else \ + { \ + (vb)[0].luma_tc.x = (zb)[0].x; (vb)[0].luma_tc.y = (zb)[0].y; \ + (vb)[1].luma_tc.x = (zb)[0].x; (vb)[1].luma_tc.y = (zb)[0].y + (hy); \ + (vb)[2].luma_tc.x = (zb)[0].x + (hx); (vb)[2].luma_tc.y = (zb)[0].y; \ + (vb)[3].luma_tc.x = (zb)[0].x + (hx); (vb)[3].luma_tc.y = (zb)[0].y; \ + (vb)[4].luma_tc.x = (zb)[0].x; (vb)[4].luma_tc.y = (zb)[0].y + (hy); \ + (vb)[5].luma_tc.x = (zb)[0].x + (hx); (vb)[5].luma_tc.y = (zb)[0].y + (hy); \ + } \ + \ + if ((cbp) & (cbm)) \ + { \ + (vb)[0].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cb_tc.y = (mby) * (unity) + (ofsy); \ + (vb)[1].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \ + (vb)[2].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cb_tc.y = (mby) * (unity) + (ofsy); \ + (vb)[3].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cb_tc.y = (mby) * (unity) + (ofsy); \ + (vb)[4].cb_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \ + (vb)[5].cb_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cb_tc.y = (mby) * (unity) + (ofsy) + (hy); \ + } \ + else \ + { \ + (vb)[0].cb_tc.x = (zb)[1].x; (vb)[0].cb_tc.y = (zb)[1].y; \ + (vb)[1].cb_tc.x = (zb)[1].x; (vb)[1].cb_tc.y = (zb)[1].y + (hy); \ + (vb)[2].cb_tc.x = (zb)[1].x + (hx); (vb)[2].cb_tc.y = (zb)[1].y; \ + (vb)[3].cb_tc.x = (zb)[1].x + (hx); (vb)[3].cb_tc.y = (zb)[1].y; \ + (vb)[4].cb_tc.x = (zb)[1].x; (vb)[4].cb_tc.y = (zb)[1].y + (hy); \ + (vb)[5].cb_tc.x = (zb)[1].x + (hx); (vb)[5].cb_tc.y = (zb)[1].y + (hy); \ + } \ + \ + if ((cbp) & (crm)) \ + { \ + (vb)[0].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[0].cr_tc.y = (mby) * (unity) + (ofsy); \ + (vb)[1].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[1].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \ + (vb)[2].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[2].cr_tc.y = (mby) * (unity) + (ofsy); \ + (vb)[3].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[3].cr_tc.y = (mby) * (unity) + (ofsy); \ + (vb)[4].cr_tc.x = (mbx) * (unitx) + (ofsx); (vb)[4].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \ + (vb)[5].cr_tc.x = (mbx) * (unitx) + (ofsx) + (hx); (vb)[5].cr_tc.y = (mby) * (unity) + (ofsy) + (hy); \ + } \ + else \ + { \ + (vb)[0].cr_tc.x = (zb)[2].x; (vb)[0].cr_tc.y = (zb)[2].y; \ + (vb)[1].cr_tc.x = (zb)[2].x; (vb)[1].cr_tc.y = (zb)[2].y + (hy); \ + (vb)[2].cr_tc.x = (zb)[2].x + (hx); (vb)[2].cr_tc.y = (zb)[2].y; \ + (vb)[3].cr_tc.x = (zb)[2].x + (hx); (vb)[3].cr_tc.y = (zb)[2].y; \ + (vb)[4].cr_tc.x = (zb)[2].x; (vb)[4].cr_tc.y = (zb)[2].y + (hy); \ + (vb)[5].cr_tc.x = (zb)[2].x + (hx); (vb)[5].cr_tc.y = (zb)[2].y + (hy); \ + } \ + } while (0) + +static inline int vlGenMacroblockVerts +( + struct vlR16SnormBufferedMC *mc, + struct vlMpeg2MacroBlock *macroblock, + unsigned int pos, + struct vlMacroBlockVertexStream0 *ycbcr_vb, + struct vlVertex2f **ref_vb +) +{ + struct vlVertex2f mo_vec[2]; + unsigned int i; + + assert(mc); + assert(macroblock); + assert(ycbcr_vb); + assert(pos < mc->macroblocks_per_picture); + + switch (macroblock->mb_type) + { + case vlMacroBlockTypeBiPredicted: + { + struct vlVertex2f *vb; + + assert(ref_vb && ref_vb[1]); + + vb = ref_vb[1] + pos * 2 * 24; + + mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x; + mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y; + + if (macroblock->mo_type == vlMotionTypeFrame) + { + for (i = 0; i < 24 * 2; i += 2) + { + vb[i].x = mo_vec[0].x; + vb[i].y = mo_vec[0].y; + } + } + else + { + mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x; + mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y; + + for (i = 0; i < 24 * 2; i += 2) + { + vb[i].x = mo_vec[0].x; + vb[i].y = mo_vec[0].y; + vb[i + 1].x = mo_vec[1].x; + vb[i + 1].y = mo_vec[1].y; + } + } + + /* fall-through */ + } + case vlMacroBlockTypeFwdPredicted: + case vlMacroBlockTypeBkwdPredicted: + { + struct vlVertex2f *vb; + + assert(ref_vb && ref_vb[0]); + + vb = ref_vb[0] + pos * 2 * 24; + + if (macroblock->mb_type == vlMacroBlockTypeBkwdPredicted) + { + mo_vec[0].x = macroblock->PMV[0][1][0] * 0.5f * mc->surface_tex_inv_size.x; + mo_vec[0].y = macroblock->PMV[0][1][1] * 0.5f * mc->surface_tex_inv_size.y; + + if (macroblock->mo_type == vlMotionTypeField) + { + mo_vec[1].x = macroblock->PMV[1][1][0] * 0.5f * mc->surface_tex_inv_size.x; + mo_vec[1].y = macroblock->PMV[1][1][1] * 0.5f * mc->surface_tex_inv_size.y; + } + } + else + { + mo_vec[0].x = macroblock->PMV[0][0][0] * 0.5f * mc->surface_tex_inv_size.x; + mo_vec[0].y = macroblock->PMV[0][0][1] * 0.5f * mc->surface_tex_inv_size.y; + + if (macroblock->mo_type == vlMotionTypeField) + { + mo_vec[1].x = macroblock->PMV[1][0][0] * 0.5f * mc->surface_tex_inv_size.x; + mo_vec[1].y = macroblock->PMV[1][0][1] * 0.5f * mc->surface_tex_inv_size.y; + } + } + + if (macroblock->mo_type == vlMotionTypeFrame) + { + for (i = 0; i < 24 * 2; i += 2) + { + vb[i].x = mo_vec[0].x; + vb[i].y = mo_vec[0].y; + } + } + else + { + for (i = 0; i < 24 * 2; i += 2) + { + vb[i].x = mo_vec[0].x; + vb[i].y = mo_vec[0].y; + vb[i + 1].x = mo_vec[1].x; + vb[i + 1].y = mo_vec[1].y; + } + } + + /* fall-through */ + } + case vlMacroBlockTypeIntra: + { + const struct vlVertex2f unit = + { + mc->surface_tex_inv_size.x * VL_MACROBLOCK_WIDTH, + mc->surface_tex_inv_size.y * VL_MACROBLOCK_HEIGHT + }; + const struct vlVertex2f half = + { + mc->surface_tex_inv_size.x * (VL_MACROBLOCK_WIDTH / 2), + mc->surface_tex_inv_size.y * (VL_MACROBLOCK_HEIGHT / 2) + }; + + struct vlMacroBlockVertexStream0 *vb; + + vb = ycbcr_vb + pos * 24; + + SET_BLOCK + ( + vb, + macroblock->cbp, macroblock->mbx, macroblock->mby, + unit.x, unit.y, 0, 0, half.x, half.y, + 32, 2, 1, mc->zero_block + ); + + SET_BLOCK + ( + vb + 6, + macroblock->cbp, macroblock->mbx, macroblock->mby, + unit.x, unit.y, half.x, 0, half.x, half.y, + 16, 2, 1, mc->zero_block + ); + + SET_BLOCK + ( + vb + 12, + macroblock->cbp, macroblock->mbx, macroblock->mby, + unit.x, unit.y, 0, half.y, half.x, half.y, + 8, 2, 1, mc->zero_block + ); + + SET_BLOCK + ( + vb + 18, + macroblock->cbp, macroblock->mbx, macroblock->mby, + unit.x, unit.y, half.x, half.y, half.x, half.y, + 4, 2, 1, mc->zero_block + ); + + break; + } + default: + assert(0); + } + + return 0; +} + +static int vlFlush +( + struct vlRender *render +) +{ + struct vlR16SnormBufferedMC *mc; + struct pipe_context *pipe; + struct vlVertexShaderConsts *vs_consts; + unsigned int num_macroblocks[vlNumMacroBlockExTypes] = {0}; + unsigned int offset[vlNumMacroBlockExTypes]; + unsigned int vb_start = 0; + unsigned int i; + + assert(render); + + mc = (struct vlR16SnormBufferedMC*)render; + + if (!mc->buffered_surface) + return 0; + + if (mc->num_macroblocks < mc->macroblocks_per_picture) + return 0; + + assert(mc->num_macroblocks <= mc->macroblocks_per_picture); + + pipe = mc->pipe; + + for (i = 0; i < mc->num_macroblocks; ++i) + { + enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]); + + num_macroblocks[mb_type_ex]++; + } + + offset[0] = 0; + + for (i = 1; i < vlNumMacroBlockExTypes; ++i) + offset[i] = offset[i - 1] + num_macroblocks[i - 1]; + + { + struct vlMacroBlockVertexStream0 *ycbcr_vb; + struct vlVertex2f *ref_vb[2]; + + ycbcr_vb = (struct vlMacroBlockVertexStream0*)pipe_buffer_map + ( + pipe->screen, + mc->vertex_bufs.ycbcr.buffer, + PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD + ); + + for (i = 0; i < 2; ++i) + ref_vb[i] = (struct vlVertex2f*)pipe_buffer_map + ( + pipe->screen, + mc->vertex_bufs.ref[i].buffer, + PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD + ); + + for (i = 0; i < mc->num_macroblocks; ++i) + { + enum vlMacroBlockTypeEx mb_type_ex = vlGetMacroBlockTypeEx(&mc->macroblocks[i]); + + vlGenMacroblockVerts(mc, &mc->macroblocks[i], offset[mb_type_ex], ycbcr_vb, ref_vb); + + offset[mb_type_ex]++; + } + + pipe_buffer_unmap(pipe->screen, mc->vertex_bufs.ycbcr.buffer); + for (i = 0; i < 2; ++i) + pipe_buffer_unmap(pipe->screen, mc->vertex_bufs.ref[i].buffer); + } + + for (i = 0; i < 3; ++i) + { + pipe_surface_unmap(mc->tex_surface[i]); + pipe_surface_reference(&mc->tex_surface[i], NULL); + } + + mc->render_target.cbufs[0] = pipe->screen->get_tex_surface + ( + pipe->screen, + mc->buffered_surface->texture, + 0, 0, 0, PIPE_BUFFER_USAGE_GPU_READ | PIPE_BUFFER_USAGE_GPU_WRITE + ); + + pipe->set_framebuffer_state(pipe, &mc->render_target); + pipe->set_viewport_state(pipe, &mc->viewport); + vs_consts = pipe_buffer_map + ( + pipe->screen, + mc->vs_const_buf.buffer, + PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD + ); + + vs_consts->denorm.x = mc->buffered_surface->texture->width[0]; + vs_consts->denorm.y = mc->buffered_surface->texture->height[0]; + + pipe_buffer_unmap(pipe->screen, mc->vs_const_buf.buffer); + pipe->set_constant_buffer(pipe, PIPE_SHADER_VERTEX, 0, &mc->vs_const_buf); + pipe->set_constant_buffer(pipe, PIPE_SHADER_FRAGMENT, 0, &mc->fs_const_buf); + + if (num_macroblocks[vlMacroBlockExTypeIntra] > 0) + { + pipe->set_vertex_buffers(pipe, 1, mc->vertex_bufs.all); + pipe->set_vertex_elements(pipe, 4, mc->vertex_elems); + pipe->set_sampler_textures(pipe, 3, mc->textures.all); + pipe->bind_sampler_states(pipe, 3, mc->samplers.all); + pipe->bind_vs_state(pipe, mc->i_vs); + pipe->bind_fs_state(pipe, mc->i_fs); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeIntra] * 24); + vb_start += num_macroblocks[vlMacroBlockExTypeIntra] * 24; + } + + if (num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] > 0) + { + pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all); + pipe->set_vertex_elements(pipe, 6, mc->vertex_elems); + mc->textures.ref[0] = mc->past_surface->texture; + pipe->set_sampler_textures(pipe, 4, mc->textures.all); + pipe->bind_sampler_states(pipe, 4, mc->samplers.all); + pipe->bind_vs_state(pipe, mc->p_vs[0]); + pipe->bind_fs_state(pipe, mc->p_fs[0]); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24); + vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedFrame] * 24; + } + + if (num_macroblocks[vlMacroBlockExTypeFwdPredictedField] > 0) + { + pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all); + pipe->set_vertex_elements(pipe, 6, mc->vertex_elems); + mc->textures.ref[0] = mc->past_surface->texture; + pipe->set_sampler_textures(pipe, 4, mc->textures.all); + pipe->bind_sampler_states(pipe, 4, mc->samplers.all); + pipe->bind_vs_state(pipe, mc->p_vs[1]); + pipe->bind_fs_state(pipe, mc->p_fs[1]); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24); + vb_start += num_macroblocks[vlMacroBlockExTypeFwdPredictedField] * 24; + } + + if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] > 0) + { + pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all); + pipe->set_vertex_elements(pipe, 6, mc->vertex_elems); + mc->textures.ref[0] = mc->future_surface->texture; + pipe->set_sampler_textures(pipe, 4, mc->textures.all); + pipe->bind_sampler_states(pipe, 4, mc->samplers.all); + pipe->bind_vs_state(pipe, mc->p_vs[0]); + pipe->bind_fs_state(pipe, mc->p_fs[0]); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24); + vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedFrame] * 24; + } + + if (num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] > 0) + { + pipe->set_vertex_buffers(pipe, 2, mc->vertex_bufs.all); + pipe->set_vertex_elements(pipe, 6, mc->vertex_elems); + mc->textures.ref[0] = mc->future_surface->texture; + pipe->set_sampler_textures(pipe, 4, mc->textures.all); + pipe->bind_sampler_states(pipe, 4, mc->samplers.all); + pipe->bind_vs_state(pipe, mc->p_vs[1]); + pipe->bind_fs_state(pipe, mc->p_fs[1]); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24); + vb_start += num_macroblocks[vlMacroBlockExTypeBkwdPredictedField] * 24; + } + + if (num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] > 0) + { + pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs.all); + pipe->set_vertex_elements(pipe, 8, mc->vertex_elems); + mc->textures.ref[0] = mc->past_surface->texture; + mc->textures.ref[1] = mc->future_surface->texture; + pipe->set_sampler_textures(pipe, 5, mc->textures.all); + pipe->bind_sampler_states(pipe, 5, mc->samplers.all); + pipe->bind_vs_state(pipe, mc->b_vs[0]); + pipe->bind_fs_state(pipe, mc->b_fs[0]); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24); + vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedFrame] * 24; + } + + if (num_macroblocks[vlMacroBlockExTypeBiPredictedField] > 0) + { + pipe->set_vertex_buffers(pipe, 3, mc->vertex_bufs.all); + pipe->set_vertex_elements(pipe, 8, mc->vertex_elems); + mc->textures.ref[0] = mc->past_surface->texture; + mc->textures.ref[1] = mc->future_surface->texture; + pipe->set_sampler_textures(pipe, 5, mc->textures.all); + pipe->bind_sampler_states(pipe, 5, mc->samplers.all); + pipe->bind_vs_state(pipe, mc->b_vs[1]); + pipe->bind_fs_state(pipe, mc->b_fs[1]); + + pipe->draw_arrays(pipe, PIPE_PRIM_TRIANGLES, vb_start, num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24); + vb_start += num_macroblocks[vlMacroBlockExTypeBiPredictedField] * 24; + } + + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &mc->buffered_surface->render_fence); + pipe_surface_reference(&mc->render_target.cbufs[0], NULL); + + for (i = 0; i < 3; ++i) + mc->zero_block[i].x = -1.0f; + + mc->buffered_surface = NULL; + mc->num_macroblocks = 0; + + return 0; +} + +static int vlRenderMacroBlocksMpeg2R16SnormBuffered +( + struct vlRender *render, + struct vlMpeg2MacroBlockBatch *batch, + struct vlSurface *surface +) +{ + struct vlR16SnormBufferedMC *mc; + bool new_surface = false; + unsigned int i; + + assert(render); + + mc = (struct vlR16SnormBufferedMC*)render; + + if (mc->buffered_surface) + { + if (mc->buffered_surface != surface) + { + vlFlush(&mc->base); + new_surface = true; + } + } + else + new_surface = true; + + if (new_surface) + { + mc->buffered_surface = surface; + mc->past_surface = batch->past_surface; + mc->future_surface = batch->future_surface; + mc->surface_tex_inv_size.x = 1.0f / surface->texture->width[0]; + mc->surface_tex_inv_size.y = 1.0f / surface->texture->height[0]; + + for (i = 0; i < 3; ++i) + { + mc->tex_surface[i] = mc->pipe->screen->get_tex_surface + ( + mc->pipe->screen, + mc->textures.all[i], + 0, 0, 0, PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD + ); + + mc->texels[i] = pipe_surface_map(mc->tex_surface[i], PIPE_BUFFER_USAGE_CPU_WRITE | PIPE_BUFFER_USAGE_DISCARD); + } + } + + for (i = 0; i < batch->num_macroblocks; ++i) + vlGrabMacroBlock(mc, &batch->macroblocks[i]); + + return 0; +} + +static inline int vlEnd +( + struct vlRender *render +) +{ + assert(render); + + return 0; +} + +static int vlDestroy +( + struct vlRender *render +) +{ + struct vlR16SnormBufferedMC *mc; + struct pipe_context *pipe; + unsigned int i; + + assert(render); + + mc = (struct vlR16SnormBufferedMC*)render; + pipe = mc->pipe; + + for (i = 0; i < 5; ++i) + pipe->delete_sampler_state(pipe, mc->samplers.all[i]); + + for (i = 0; i < 3; ++i) + pipe_buffer_reference(pipe->screen, &mc->vertex_bufs.all[i].buffer, NULL); + + /* Textures 3 & 4 are not created directly, no need to release them here */ + for (i = 0; i < 3; ++i) + pipe_texture_reference(&mc->textures.all[i], NULL); + + pipe->delete_vs_state(pipe, mc->i_vs); + pipe->delete_fs_state(pipe, mc->i_fs); + + for (i = 0; i < 2; ++i) + { + pipe->delete_vs_state(pipe, mc->p_vs[i]); + pipe->delete_fs_state(pipe, mc->p_fs[i]); + pipe->delete_vs_state(pipe, mc->b_vs[i]); + pipe->delete_fs_state(pipe, mc->b_fs[i]); + } + + pipe_buffer_reference(pipe->screen, &mc->vs_const_buf.buffer, NULL); + pipe_buffer_reference(pipe->screen, &mc->fs_const_buf.buffer, NULL); + + FREE(mc->macroblocks); + FREE(mc); + + return 0; +} + +/* + * Muliplier renormalizes block samples from 16 bits to 12 bits. + * Divider is used when calculating Y % 2 for choosing top or bottom + * field for P or B macroblocks. + * TODO: Use immediates. + */ +static const struct vlFragmentShaderConsts fs_consts = +{ + {32767.0f / 255.0f, 32767.0f / 255.0f, 32767.0f / 255.0f, 0.0f}, + {0.5f, 2.0f, 0.0f, 0.0f} +}; + +#include "vl_r16snorm_mc_buf_shaders.inc" + +static int vlCreateDataBufs +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int mbw = align(mc->picture_width, VL_MACROBLOCK_WIDTH) / VL_MACROBLOCK_WIDTH; + const unsigned int mbh = align(mc->picture_height, VL_MACROBLOCK_HEIGHT) / VL_MACROBLOCK_HEIGHT; + + struct pipe_context *pipe; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + mc->macroblocks_per_picture = mbw * mbh; + + /* Create our vertex buffers */ + mc->vertex_bufs.ycbcr.stride = sizeof(struct vlVertex2f) * 4; + mc->vertex_bufs.ycbcr.max_index = 24 * mc->macroblocks_per_picture - 1; + mc->vertex_bufs.ycbcr.buffer_offset = 0; + mc->vertex_bufs.ycbcr.buffer = pipe_buffer_create + ( + pipe->screen, + DEFAULT_BUF_ALIGNMENT, + PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_DISCARD, + sizeof(struct vlVertex2f) * 4 * 24 * mc->macroblocks_per_picture + ); + + for (i = 1; i < 3; ++i) + { + mc->vertex_bufs.all[i].stride = sizeof(struct vlVertex2f) * 2; + mc->vertex_bufs.all[i].max_index = 24 * mc->macroblocks_per_picture - 1; + mc->vertex_bufs.all[i].buffer_offset = 0; + mc->vertex_bufs.all[i].buffer = pipe_buffer_create + ( + pipe->screen, + DEFAULT_BUF_ALIGNMENT, + PIPE_BUFFER_USAGE_VERTEX | PIPE_BUFFER_USAGE_DISCARD, + sizeof(struct vlVertex2f) * 2 * 24 * mc->macroblocks_per_picture + ); + } + + /* Position element */ + mc->vertex_elems[0].src_offset = 0; + mc->vertex_elems[0].vertex_buffer_index = 0; + mc->vertex_elems[0].nr_components = 2; + mc->vertex_elems[0].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Luma, texcoord element */ + mc->vertex_elems[1].src_offset = sizeof(struct vlVertex2f); + mc->vertex_elems[1].vertex_buffer_index = 0; + mc->vertex_elems[1].nr_components = 2; + mc->vertex_elems[1].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Chroma Cr texcoord element */ + mc->vertex_elems[2].src_offset = sizeof(struct vlVertex2f) * 2; + mc->vertex_elems[2].vertex_buffer_index = 0; + mc->vertex_elems[2].nr_components = 2; + mc->vertex_elems[2].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Chroma Cb texcoord element */ + mc->vertex_elems[3].src_offset = sizeof(struct vlVertex2f) * 3; + mc->vertex_elems[3].vertex_buffer_index = 0; + mc->vertex_elems[3].nr_components = 2; + mc->vertex_elems[3].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* First ref surface top field texcoord element */ + mc->vertex_elems[4].src_offset = 0; + mc->vertex_elems[4].vertex_buffer_index = 1; + mc->vertex_elems[4].nr_components = 2; + mc->vertex_elems[4].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* First ref surface bottom field texcoord element */ + mc->vertex_elems[5].src_offset = sizeof(struct vlVertex2f); + mc->vertex_elems[5].vertex_buffer_index = 1; + mc->vertex_elems[5].nr_components = 2; + mc->vertex_elems[5].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Second ref surface top field texcoord element */ + mc->vertex_elems[6].src_offset = 0; + mc->vertex_elems[6].vertex_buffer_index = 2; + mc->vertex_elems[6].nr_components = 2; + mc->vertex_elems[6].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Second ref surface bottom field texcoord element */ + mc->vertex_elems[7].src_offset = sizeof(struct vlVertex2f); + mc->vertex_elems[7].vertex_buffer_index = 2; + mc->vertex_elems[7].nr_components = 2; + mc->vertex_elems[7].src_format = PIPE_FORMAT_R32G32_FLOAT; + + /* Create our constant buffer */ + mc->vs_const_buf.buffer = pipe_buffer_create + ( + pipe->screen, + DEFAULT_BUF_ALIGNMENT, + PIPE_BUFFER_USAGE_CONSTANT | PIPE_BUFFER_USAGE_DISCARD, + sizeof(struct vlVertexShaderConsts) + ); + + mc->fs_const_buf.buffer = pipe_buffer_create + ( + pipe->screen, + DEFAULT_BUF_ALIGNMENT, + PIPE_BUFFER_USAGE_CONSTANT, + sizeof(struct vlFragmentShaderConsts) + ); + + memcpy + ( + pipe_buffer_map(pipe->screen, mc->fs_const_buf.buffer, PIPE_BUFFER_USAGE_CPU_WRITE), + &fs_consts, + sizeof(struct vlFragmentShaderConsts) + ); + + pipe_buffer_unmap(pipe->screen, mc->fs_const_buf.buffer); + + mc->macroblocks = MALLOC(sizeof(struct vlMpeg2MacroBlock) * mc->macroblocks_per_picture); + + return 0; +} + +static int vlInit +( + struct vlR16SnormBufferedMC *mc +) +{ + struct pipe_context *pipe; + struct pipe_sampler_state sampler; + struct pipe_texture template; + unsigned int filters[5]; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + + mc->buffered_surface = NULL; + mc->past_surface = NULL; + mc->future_surface = NULL; + for (i = 0; i < 3; ++i) + mc->zero_block[i].x = -1.0f; + mc->num_macroblocks = 0; + + /* For MC we render to textures, which are rounded up to nearest POT */ + mc->viewport.scale[0] = vlRoundUpPOT(mc->picture_width); + mc->viewport.scale[1] = vlRoundUpPOT(mc->picture_height); + mc->viewport.scale[2] = 1; + mc->viewport.scale[3] = 1; + mc->viewport.translate[0] = 0; + mc->viewport.translate[1] = 0; + mc->viewport.translate[2] = 0; + mc->viewport.translate[3] = 0; + + mc->render_target.width = vlRoundUpPOT(mc->picture_width); + mc->render_target.height = vlRoundUpPOT(mc->picture_height); + mc->render_target.nr_cbufs = 1; + /* FB for MC stage is a vlSurface created by the user, set at render time */ + mc->render_target.zsbuf = NULL; + + filters[0] = PIPE_TEX_FILTER_NEAREST; + /* FIXME: Linear causes discoloration around block edges */ + filters[1] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST /*: PIPE_TEX_FILTER_LINEAR*/; + filters[2] = /*mc->picture_format == vlFormatYCbCr444 ?*/ PIPE_TEX_FILTER_NEAREST /*: PIPE_TEX_FILTER_LINEAR*/; + filters[3] = PIPE_TEX_FILTER_LINEAR; + filters[4] = PIPE_TEX_FILTER_LINEAR; + + for (i = 0; i < 5; ++i) + { + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.min_img_filter = filters[i]; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE; + sampler.mag_img_filter = filters[i]; + sampler.compare_mode = PIPE_TEX_COMPARE_NONE; + sampler.compare_func = PIPE_FUNC_ALWAYS; + sampler.normalized_coords = 1; + /*sampler.prefilter = ;*/ + /*sampler.shadow_ambient = ;*/ + /*sampler.lod_bias = ;*/ + sampler.min_lod = 0; + /*sampler.max_lod = ;*/ + /*sampler.border_color[i] = ;*/ + /*sampler.max_anisotropy = ;*/ + mc->samplers.all[i] = pipe->create_sampler_state(pipe, &sampler); + } + + memset(&template, 0, sizeof(struct pipe_texture)); + template.target = PIPE_TEXTURE_2D; + template.format = PIPE_FORMAT_R16_SNORM; + template.last_level = 0; + template.width[0] = vlRoundUpPOT(mc->picture_width); + template.height[0] = vlRoundUpPOT(mc->picture_height); + template.depth[0] = 1; + template.compressed = 0; + pf_get_block(template.format, &template.block); + template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_DYNAMIC; + + mc->textures.y = pipe->screen->texture_create(pipe->screen, &template); + + if (mc->picture_format == vlFormatYCbCr420) + { + template.width[0] = vlRoundUpPOT(mc->picture_width / 2); + template.height[0] = vlRoundUpPOT(mc->picture_height / 2); + } + else if (mc->picture_format == vlFormatYCbCr422) + template.height[0] = vlRoundUpPOT(mc->picture_height / 2); + + mc->textures.cb = pipe->screen->texture_create(pipe->screen, &template); + mc->textures.cr = pipe->screen->texture_create(pipe->screen, &template); + + /* textures.all[3] & textures.all[4] are assigned from vlSurfaces for P and B macroblocks at render time */ + + vlCreateVertexShaderIMB(mc); + vlCreateFragmentShaderIMB(mc); + vlCreateVertexShaderFramePMB(mc); + vlCreateVertexShaderFieldPMB(mc); + vlCreateFragmentShaderFramePMB(mc); + vlCreateFragmentShaderFieldPMB(mc); + vlCreateVertexShaderFrameBMB(mc); + vlCreateVertexShaderFieldBMB(mc); + vlCreateFragmentShaderFrameBMB(mc); + vlCreateFragmentShaderFieldBMB(mc); + vlCreateDataBufs(mc); + + return 0; +} + +int vlCreateR16SNormBufferedMC +( + struct pipe_context *pipe, + unsigned int picture_width, + unsigned int picture_height, + enum vlFormat picture_format, + struct vlRender **render +) +{ + struct vlR16SnormBufferedMC *mc; + + assert(pipe); + assert(render); + + mc = CALLOC_STRUCT(vlR16SnormBufferedMC); + + mc->base.vlBegin = &vlBegin; + mc->base.vlRenderMacroBlocksMpeg2 = &vlRenderMacroBlocksMpeg2R16SnormBuffered; + mc->base.vlEnd = &vlEnd; + mc->base.vlFlush = &vlFlush; + mc->base.vlDestroy = &vlDestroy; + mc->pipe = pipe; + mc->picture_width = picture_width; + mc->picture_height = picture_height; + + vlInit(mc); + + *render = &mc->base; + + return 0; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h new file mode 100644 index 00000000000..27177d64cad --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf.h @@ -0,0 +1,18 @@ +#ifndef vl_r16snorm_mc_buf_h +#define vl_r16snorm_mc_buf_h + +#include "vl_types.h" + +struct pipe_context; +struct vlRender; + +int vlCreateR16SNormBufferedMC +( + struct pipe_context *pipe, + unsigned int picture_width, + unsigned int picture_height, + enum vlFormat picture_format, + struct vlRender **render +); + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc new file mode 100644 index 00000000000..ef4a4b2add9 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_r16snorm_mc_buf_shaders.inc @@ -0,0 +1,1185 @@ +static int vlCreateVertexShaderIMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 50; + + struct pipe_context *pipe; + struct pipe_shader_state vs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + + ti = 3; + + /* + * decl i0 ; Vertex pos + * decl i1 ; Luma texcoords + * decl i2 ; Chroma Cb texcoords + * decl i3 ; Chroma Cr texcoords + */ + for (i = 0; i < 4; i++) + { + decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * decl o0 ; Vertex pos + * decl o1 ; Luma texcoords + * decl o2 ; Chroma Cb texcoords + * decl o3 ; Chroma Cr texcoords + */ + for (i = 0; i < 4; i++) + { + decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * mov o0, i0 ; Move input vertex pos to output + * mov o1, i1 ; Move input luma texcoords to output + * mov o2, i2 ; Move input chroma Cb texcoords to output + * mov o3, i3 ; Move input chroma Cr texcoords to output + */ + for (i = 0; i < 4; ++i) + { + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + vs.tokens = tokens; + mc->i_vs = pipe->create_vs_state(pipe, &vs); + free(tokens); + + return 0; +} + +static int vlCreateFragmentShaderIMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 100; + + struct pipe_context *pipe; + struct pipe_shader_state fs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + + ti = 3; + + /* + * decl i0 ; Luma texcoords + * decl i1 ; Chroma Cb texcoords + * decl i2 ; Chroma Cr texcoords + */ + for (i = 0; i < 3; ++i) + { + decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */ + decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl o0 ; Fragment color */ + decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl t0, t1 */ + decl = vl_decl_temps(0, 1); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * decl s0 ; Sampler for luma texture + * decl s1 ; Sampler for chroma Cb texture + * decl s2 ; Sampler for chroma Cr texture + */ + for (i = 0; i < 3; ++i) + { + decl = vl_decl_samplers(i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header,max_tokens - ti); + } + + /* + * tex2d t1, i0, s0 ; Read texel from luma texture + * mov t0.x, t1.x ; Move luma sample into .x component + * tex2d t1, i1, s1 ; Read texel from chroma Cb texture + * mov t0.y, t1.x ; Move Cb sample into .y component + * tex2d t1, i2, s2 ; Read texel from chroma Cr texture + * mov t0.z, t1.x ; Move Cr sample into .z component + */ + for (i = 0; i < 3; ++i) + { + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); + inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* mul o0, t0, c0 ; Rescale texel to correct range */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + fs.tokens = tokens; + mc->i_fs = pipe->create_fs_state(pipe, &fs); + free(tokens); + + return 0; +} + +static int vlCreateVertexShaderFramePMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 100; + + struct pipe_context *pipe; + struct pipe_shader_state vs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + + ti = 3; + + /* + * decl i0 ; Vertex pos + * decl i1 ; Luma texcoords + * decl i2 ; Chroma Cb texcoords + * decl i3 ; Chroma Cr texcoords + * decl i4 ; Ref surface top field texcoords + * decl i5 ; Ref surface bottom field texcoords (unused, packed in the same stream) + */ + for (i = 0; i < 6; i++) + { + decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * decl o0 ; Vertex pos + * decl o1 ; Luma texcoords + * decl o2 ; Chroma Cb texcoords + * decl o3 ; Chroma Cr texcoords + * decl o4 ; Ref macroblock texcoords + */ + for (i = 0; i < 5; i++) + { + decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * mov o0, i0 ; Move input vertex pos to output + * mov o1, i1 ; Move input luma texcoords to output + * mov o2, i2 ; Move input chroma Cb texcoords to output + * mov o3, i3 ; Move input chroma Cr texcoords to output + */ + for (i = 0; i < 4; ++i) + { + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* add o4, i0, i4 ; Translate vertex pos by motion vec to form ref macroblock texcoords */ + inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, 4); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + vs.tokens = tokens; + mc->p_vs[0] = pipe->create_vs_state(pipe, &vs); + free(tokens); + + return 0; +} + +static int vlCreateVertexShaderFieldPMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 100; + + struct pipe_context *pipe; + struct pipe_shader_state vs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + + ti = 3; + + /* + * decl i0 ; Vertex pos + * decl i1 ; Luma texcoords + * decl i2 ; Chroma Cb texcoords + * decl i3 ; Chroma Cr texcoords + * decl i4 ; Ref macroblock top field texcoords + * decl i5 ; Ref macroblock bottom field texcoords + */ + for (i = 0; i < 6; i++) + { + decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* decl c0 ; Render target dimensions */ + decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * decl o0 ; Vertex pos + * decl o1 ; Luma texcoords + * decl o2 ; Chroma Cb texcoords + * decl o3 ; Chroma Cr texcoords + * decl o4 ; Ref macroblock top field texcoords + * decl o5 ; Ref macroblock bottom field texcoords + * decl o6 ; Denormalized vertex pos + */ + for (i = 0; i < 7; i++) + { + decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * mov o0, i0 ; Move input vertex pos to output + * mov o1, i1 ; Move input luma texcoords to output + * mov o2, i2 ; Move input chroma Cb texcoords to output + * mov o3, i3 ; Move input chroma Cr texcoords to output + */ + for (i = 0; i < 4; ++i) + { + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* + * add o4, i0, i4 ; Translate vertex pos by motion vec to form top field macroblock texcoords + * add o5, i0, i5 ; Translate vertex pos by motion vec to form bottom field macroblock texcoords + */ + for (i = 0; i < 2; ++i) + { + inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, i + 4); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* mul o6, i0, c0 ; Denorm vertex pos */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 6, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + vs.tokens = tokens; + mc->p_vs[1] = pipe->create_vs_state(pipe, &vs); + free(tokens); + + return 0; +} + +static int vlCreateFragmentShaderFramePMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 100; + + struct pipe_context *pipe; + struct pipe_shader_state fs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + + ti = 3; + + /* + * decl i0 ; Luma texcoords + * decl i1 ; Chroma Cb texcoords + * decl i2 ; Chroma Cr texcoords + * decl i3 ; Ref macroblock texcoords + */ + for (i = 0; i < 4; ++i) + { + decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm */ + decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl o0 ; Fragment color */ + decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl t0, t1 */ + decl = vl_decl_temps(0, 1); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * decl s0 ; Sampler for luma texture + * decl s1 ; Sampler for chroma Cb texture + * decl s2 ; Sampler for chroma Cr texture + * decl s3 ; Sampler for ref surface texture + */ + for (i = 0; i < 4; ++i) + { + decl = vl_decl_samplers(i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * tex2d t1, i0, s0 ; Read texel from luma texture + * mov t0.x, t1.x ; Move luma sample into .x component + * tex2d t1, i1, s1 ; Read texel from chroma Cb texture + * mov t0.y, t1.x ; Move Cb sample into .y component + * tex2d t1, i2, s2 ; Read texel from chroma Cr texture + * mov t0.z, t1.x ; Move Cr sample into .z component + */ + for (i = 0; i < 3; ++i) + { + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); + inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* mul t0, t0, c0 ; Rescale texel to correct range */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* tex2d t1, i3, s3 ; Read texel from ref macroblock */ + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, 3, TGSI_FILE_SAMPLER, 3); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* add o0, t0, t1 ; Add ref and differential to form final output */ + inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + fs.tokens = tokens; + mc->p_fs[0] = pipe->create_fs_state(pipe, &fs); + free(tokens); + + return 0; +} + +static int vlCreateFragmentShaderFieldPMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 200; + + struct pipe_context *pipe; + struct pipe_shader_state fs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + + ti = 3; + + /* + * decl i0 ; Luma texcoords + * decl i1 ; Chroma Cb texcoords + * decl i2 ; Chroma Cr texcoords + * decl i3 ; Ref macroblock top field texcoords + * decl i4 ; Ref macroblock bottom field texcoords + * decl i5 ; Denormalized vertex pos + */ + for (i = 0; i < 6; ++i) + { + decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm + * decl c1 ; Constants 1/2 & 2 in .x, .y channels for Y-mod-2 top/bottom field selection + */ + decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl o0 ; Fragment color */ + decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl t0-t4 */ + decl = vl_decl_temps(0, 4); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * decl s0 ; Sampler for luma texture + * decl s1 ; Sampler for chroma Cb texture + * decl s2 ; Sampler for chroma Cr texture + * decl s3 ; Sampler for ref surface texture + */ + for (i = 0; i < 4; ++i) + { + decl = vl_decl_samplers(i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * tex2d t1, i0, s0 ; Read texel from luma texture + * mov t0.x, t1.x ; Move luma sample into .x component + * tex2d t1, i1, s1 ; Read texel from chroma Cb texture + * mov t0.y, t1.x ; Move Cb sample into .y component + * tex2d t1, i2, s2 ; Read texel from chroma Cr texture + * mov t0.z, t1.x ; Move Cr sample into .z component + */ + for (i = 0; i < 3; ++i) + { + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); + inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* mul t0, t0, c0 ; Rescale texel to correct range */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* + * tex2d t1, i3, s3 ; Read texel from ref macroblock top field + * tex2d t2, i4, s3 ; Read texel from ref macroblock bottom field + */ + for (i = 0; i < 2; ++i) + { + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 3, TGSI_FILE_SAMPLER, 3); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* XXX: Pos values off by 0.5? */ + /* sub t4, i5.y, c1.x ; Sub 0.5 from denormalized pos */ + inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 5, TGSI_FILE_CONSTANT, 1); + inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* mul t3, t4, c1.x ; Multiply pos Y-coord by 1/2 */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_CONSTANT, 1); + inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* floor t3, t3 ; Get rid of fractional part */ + inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* mul t3, t3, c1.y ; Multiply by 2 */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1); + inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* sub t3, t4, t3 ; Subtract from original Y to get Y % 2 */ + inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 3); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* TODO: Move to conditional tex fetch on t3 instead of lerp */ + /* lerp t1, t3, t1, t2 ; Choose between top and bottom fields based on Y % 2 */ + inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* add o0, t0, t1 ; Add ref and differential to form final output */ + inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + fs.tokens = tokens; + mc->p_fs[1] = pipe->create_fs_state(pipe, &fs); + free(tokens); + + return 0; +} + +static int vlCreateVertexShaderFrameBMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 100; + + struct pipe_context *pipe; + struct pipe_shader_state vs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + + ti = 3; + + /* + * decl i0 ; Vertex pos + * decl i1 ; Luma texcoords + * decl i2 ; Chroma Cb texcoords + * decl i3 ; Chroma Cr texcoords + * decl i4 ; First ref macroblock top field texcoords + * decl i5 ; First ref macroblock bottom field texcoords (unused, packed in the same stream) + * decl i6 ; Second ref macroblock top field texcoords + * decl i7 ; Second ref macroblock bottom field texcoords (unused, packed in the same stream) + */ + for (i = 0; i < 8; i++) + { + decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * decl o0 ; Vertex pos + * decl o1 ; Luma texcoords + * decl o2 ; Chroma Cb texcoords + * decl o3 ; Chroma Cr texcoords + * decl o4 ; First ref macroblock texcoords + * decl o5 ; Second ref macroblock texcoords + */ + for (i = 0; i < 6; i++) + { + decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * mov o0, i0 ; Move input vertex pos to output + * mov o1, i1 ; Move input luma texcoords to output + * mov o2, i2 ; Move input chroma Cb texcoords to output + * mov o3, i3 ; Move input chroma Cr texcoords to output + */ + for (i = 0; i < 4; ++i) + { + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* + * add o4, i0, i4 ; Translate vertex pos by motion vec to form first ref macroblock texcoords + * add o5, i0, i6 ; Translate vertex pos by motion vec to form second ref macroblock texcoords + */ + for (i = 0; i < 2; ++i) + { + inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, (i + 2) * 2); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + vs.tokens = tokens; + mc->b_vs[0] = pipe->create_vs_state(pipe, &vs); + free(tokens); + + return 0; +} + +static int vlCreateVertexShaderFieldBMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 100; + + struct pipe_context *pipe; + struct pipe_shader_state vs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_VERTEX, header); + + ti = 3; + + /* + * decl i0 ; Vertex pos + * decl i1 ; Luma texcoords + * decl i2 ; Chroma Cb texcoords + * decl i3 ; Chroma Cr texcoords + * decl i4 ; First ref macroblock top field texcoords + * decl i5 ; First ref macroblock bottom field texcoords + * decl i6 ; Second ref macroblock top field texcoords + * decl i7 ; Second ref macroblock bottom field texcoords + */ + for (i = 0; i < 8; i++) + { + decl = vl_decl_input(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* decl c0 ; Render target dimensions */ + decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * decl o0 ; Vertex pos + * decl o1 ; Luma texcoords + * decl o2 ; Chroma Cb texcoords + * decl o3 ; Chroma Cr texcoords + * decl o4 ; First ref macroblock top field texcoords + * decl o5 ; First ref macroblock Bottom field texcoords + * decl o6 ; Second ref macroblock top field texcoords + * decl o7 ; Second ref macroblock Bottom field texcoords + * decl o8 ; Denormalized vertex pos + */ + for (i = 0; i < 9; i++) + { + decl = vl_decl_output(i == 0 ? TGSI_SEMANTIC_POSITION : TGSI_SEMANTIC_GENERIC, i, i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* decl t0, t1 */ + decl = vl_decl_temps(0, 1); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * mov o0, i0 ; Move input vertex pos to output + * mov o1, i1 ; Move input luma texcoords to output + * mov o2, i2 ; Move input chroma Cb texcoords to output + * mov o3, i3 ; Move input chroma Cr texcoords to output + */ + for (i = 0; i < 4; ++i) + { + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_OUTPUT, i, TGSI_FILE_INPUT, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* + * add o4, i0, i4 ; Translate vertex pos by motion vec to form first top field macroblock texcoords + * add o5, i0, i5 ; Translate vertex pos by motion vec to form first bottom field macroblock texcoords + * add o6, i0, i6 ; Translate vertex pos by motion vec to form second top field macroblock texcoords + * add o7, i0, i7 ; Translate vertex pos by motion vec to form second bottom field macroblock texcoords + */ + for (i = 0; i < 4; ++i) + { + inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, i + 4, TGSI_FILE_INPUT, 0, TGSI_FILE_INPUT, i + 4); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* mul o8, i0, c0 ; Denorm vertex pos */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_OUTPUT, 8, TGSI_FILE_INPUT, 0, TGSI_FILE_CONSTANT, 0); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + vs.tokens = tokens; + mc->b_vs[1] = pipe->create_vs_state(pipe, &vs); + free(tokens); + + return 0; +} + +static int vlCreateFragmentShaderFrameBMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 100; + + struct pipe_context *pipe; + struct pipe_shader_state fs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + + ti = 3; + + /* + * decl i0 ; Luma texcoords + * decl i1 ; Chroma Cb texcoords + * decl i2 ; Chroma Cr texcoords + * decl i3 ; First ref macroblock texcoords + * decl i4 ; Second ref macroblock texcoords + */ + for (i = 0; i < 5; ++i) + { + decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm + * decl c1 ; Constant 1/2 in .x channel to use as weight to blend past and future texels + */ + decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl o0 ; Fragment color */ + decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl t0-t2 */ + decl = vl_decl_temps(0, 2); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * decl s0 ; Sampler for luma texture + * decl s1 ; Sampler for chroma Cb texture + * decl s2 ; Sampler for chroma Cr texture + * decl s3 ; Sampler for first ref surface texture + * decl s4 ; Sampler for second ref surface texture + */ + for (i = 0; i < 5; ++i) + { + decl = vl_decl_samplers(i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * tex2d t1, i0, s0 ; Read texel from luma texture + * mov t0.x, t1.x ; Move luma sample into .x component + * tex2d t1, i1, s1 ; Read texel from chroma Cb texture + * mov t0.y, t1.x ; Move Cb sample into .y component + * tex2d t1, i2, s2 ; Read texel from chroma Cr texture + * mov t0.z, t1.x ; Move Cr sample into .z component + */ + for (i = 0; i < 3; ++i) + { + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); + inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* mul t0, t0, c0 ; Rescale texel to correct range */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* + * tex2d t1, i3, s3 ; Read texel from first ref macroblock + * tex2d t2, i4, s4 ; Read texel from second ref macroblock + */ + for (i = 0; i < 2; ++i) + { + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 3, TGSI_FILE_SAMPLER, i + 3); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* lerp t1, c1.x, t1, t2 ; Blend past and future texels */ + inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2); + inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* add o0, t0, t1 ; Add past/future ref and differential to form final output */ + inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + fs.tokens = tokens; + mc->b_fs[0] = pipe->create_fs_state(pipe, &fs); + free(tokens); + + return 0; +} + +static int vlCreateFragmentShaderFieldBMB +( + struct vlR16SnormBufferedMC *mc +) +{ + const unsigned int max_tokens = 200; + + struct pipe_context *pipe; + struct pipe_shader_state fs; + struct tgsi_token *tokens; + struct tgsi_header *header; + + struct tgsi_full_declaration decl; + struct tgsi_full_instruction inst; + + unsigned int ti; + unsigned int i; + + assert(mc); + + pipe = mc->pipe; + tokens = (struct tgsi_token*)malloc(max_tokens * sizeof(struct tgsi_token)); + + /* Version */ + *(struct tgsi_version*)&tokens[0] = tgsi_build_version(); + /* Header */ + header = (struct tgsi_header*)&tokens[1]; + *header = tgsi_build_header(); + /* Processor */ + *(struct tgsi_processor*)&tokens[2] = tgsi_build_processor(TGSI_PROCESSOR_FRAGMENT, header); + + ti = 3; + + /* + * decl i0 ; Luma texcoords + * decl i1 ; Chroma Cb texcoords + * decl i2 ; Chroma Cr texcoords + * decl i3 ; First ref macroblock top field texcoords + * decl i4 ; First ref macroblock bottom field texcoords + * decl i5 ; Second ref macroblock top field texcoords + * decl i6 ; Second ref macroblock bottom field texcoords + * decl i7 ; Denormalized vertex pos + */ + for (i = 0; i < 8; ++i) + { + decl = vl_decl_interpolated_input(TGSI_SEMANTIC_GENERIC, i + 1, i, i, TGSI_INTERPOLATE_LINEAR); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * decl c0 ; Scaling factor, rescales 16-bit snorm to 9-bit snorm + * decl c1 ; Constants 1/2 & 2 in .x, .y channels to use as weight to blend past and future texels + * ; and for Y-mod-2 top/bottom field selection + */ + decl = vl_decl_constants(TGSI_SEMANTIC_GENERIC, 0, 0, 1); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl o0 ; Fragment color */ + decl = vl_decl_output(TGSI_SEMANTIC_COLOR, 0, 0, 0); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* decl t0-t5 */ + decl = vl_decl_temps(0, 5); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + + /* + * decl s0 ; Sampler for luma texture + * decl s1 ; Sampler for chroma Cb texture + * decl s2 ; Sampler for chroma Cr texture + * decl s3 ; Sampler for first ref surface texture + * decl s4 ; Sampler for second ref surface texture + */ + for (i = 0; i < 5; ++i) + { + decl = vl_decl_samplers(i, i); + ti += tgsi_build_full_declaration(&decl, &tokens[ti], header, max_tokens - ti); + } + + /* + * tex2d t1, i0, s0 ; Read texel from luma texture + * mov t0.x, t1.x ; Move luma sample into .x component + * tex2d t1, i1, s1 ; Read texel from chroma Cb texture + * mov t0.y, t1.x ; Move Cb sample into .y component + * tex2d t1, i2, s2 ; Read texel from chroma Cr texture + * mov t0.z, t1.x ; Move Cr sample into .z component + */ + for (i = 0; i < 3; ++i) + { + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_INPUT, i, TGSI_FILE_SAMPLER, i); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + inst = vl_inst2(TGSI_OPCODE_MOV, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); + inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullDstRegisters[0].DstRegister.WriteMask = TGSI_WRITEMASK_X << i; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* mul t0, t0, c0 ; Rescale texel to correct range */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_CONSTANT, 0); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* XXX: Pos values off by 0.5? */ + /* sub t4, i7.y, c1.x ; Sub 0.5 from denormalized pos */ + inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_INPUT, 7, TGSI_FILE_CONSTANT, 1); + inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* mul t3, t4, c1.x ; Multiply pos Y-coord by 1/2 */ + inst = vl_inst3(TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_CONSTANT, 1); + inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* floor t3, t3 ; Get rid of fractional part */ + inst = vl_inst2(TGSI_OPCODE_FLOOR, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* mul t3, t3, c1.y ; Multiply by 2 */ + inst = vl_inst3( TGSI_OPCODE_MUL, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_CONSTANT, 1); + inst.FullSrcRegisters[1].SrcRegister.SwizzleX = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[1].SrcRegister.SwizzleY = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[1].SrcRegister.SwizzleZ = TGSI_SWIZZLE_Y; + inst.FullSrcRegisters[1].SrcRegister.SwizzleW = TGSI_SWIZZLE_Y; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* sub t3, t4, t3 ; Subtract from original Y to get Y % 2 */ + inst = vl_inst3(TGSI_OPCODE_SUB, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 3); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* + * tex2d t1, i3, s3 ; Read texel from past ref macroblock top field + * tex2d t2, i4, s3 ; Read texel from past ref macroblock bottom field + */ + for (i = 0; i < 2; ++i) + { + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 1, TGSI_FILE_INPUT, i + 3, TGSI_FILE_SAMPLER, 3); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* TODO: Move to conditional tex fetch on t3 instead of lerp */ + /* lerp t1, t3, t1, t2 ; Choose between top and bottom fields based on Y % 2 */ + inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* + * tex2d t4, i5, s4 ; Read texel from future ref macroblock top field + * tex2d t5, i6, s4 ; Read texel from future ref macroblock bottom field + */ + for (i = 0; i < 2; ++i) + { + inst = vl_tex(TGSI_TEXTURE_2D, TGSI_FILE_TEMPORARY, i + 4, TGSI_FILE_INPUT, i + 5, TGSI_FILE_SAMPLER, 4); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + } + + /* TODO: Move to conditional tex fetch on t3 instead of lerp */ + /* lerp t2, t3, t4, t5 ; Choose between top and bottom fields based on Y % 2 */ + inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 2, TGSI_FILE_TEMPORARY, 3, TGSI_FILE_TEMPORARY, 4, TGSI_FILE_TEMPORARY, 5); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* lerp t1, c1.x, t1, t2 ; Blend past and future texels */ + inst = vl_inst4(TGSI_OPCODE_LERP, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_CONSTANT, 1, TGSI_FILE_TEMPORARY, 1, TGSI_FILE_TEMPORARY, 2); + inst.FullSrcRegisters[0].SrcRegister.SwizzleX = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleY = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleZ = TGSI_SWIZZLE_X; + inst.FullSrcRegisters[0].SrcRegister.SwizzleW = TGSI_SWIZZLE_X; + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* add o0, t0, t1 ; Add past/future ref and differential to form final output */ + inst = vl_inst3(TGSI_OPCODE_ADD, TGSI_FILE_OUTPUT, 0, TGSI_FILE_TEMPORARY, 0, TGSI_FILE_TEMPORARY, 1); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + /* end */ + inst = vl_end(); + ti += tgsi_build_full_instruction(&inst, &tokens[ti], header, max_tokens - ti); + + fs.tokens = tokens; + mc->b_fs[1] = pipe->create_fs_state(pipe, &fs); + free(tokens); + + return 0; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_render.h b/src/gallium/state_trackers/g3dvl/vl_render.h new file mode 100644 index 00000000000..166030b4988 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_render.h @@ -0,0 +1,38 @@ +#ifndef vl_render_h +#define vl_render_h + +#include "vl_types.h" + +struct pipe_surface; + +struct vlRender +{ + int (*vlBegin) + ( + struct vlRender *render + ); + + int (*vlRenderMacroBlocksMpeg2) + ( + struct vlRender *render, + struct vlMpeg2MacroBlockBatch *batch, + struct vlSurface *surface + ); + + int (*vlEnd) + ( + struct vlRender *render + ); + + int (*vlFlush) + ( + struct vlRender *render + ); + + int (*vlDestroy) + ( + struct vlRender *render + ); +}; + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_screen.c b/src/gallium/state_trackers/g3dvl/vl_screen.c new file mode 100644 index 00000000000..ade8643a66a --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_screen.c @@ -0,0 +1,115 @@ +#define VL_INTERNAL +#include "vl_screen.h" +#include <assert.h> +#include <util/u_memory.h> + +int vlCreateScreen +( + struct vlDisplay *display, + int screen, + struct pipe_screen *pscreen, + struct vlScreen **vl_screen +) +{ + struct vlScreen *scrn; + + assert(display); + assert(pscreen); + assert(vl_screen); + + scrn = CALLOC_STRUCT(vlScreen); + + if (!scrn) + return 1; + + scrn->display = display; + scrn->ordinal = screen; + scrn->pscreen = pscreen; + *vl_screen = scrn; + + return 0; +} + +int vlDestroyScreen +( + struct vlScreen *screen +) +{ + assert(screen); + + FREE(screen); + + return 0; +} + +struct vlDisplay* vlGetDisplay +( + struct vlScreen *screen +) +{ + assert(screen); + + return screen->display; +} + +struct pipe_screen* vlGetPipeScreen +( + struct vlScreen *screen +) +{ + assert(screen); + + return screen->pscreen; +} + +unsigned int vlGetMaxProfiles +( + struct vlScreen *screen +) +{ + assert(screen); + + return vlProfileCount; +} + +int vlQueryProfiles +( + struct vlScreen *screen, + enum vlProfile *profiles +) +{ + assert(screen); + assert(profiles); + + profiles[0] = vlProfileMpeg2Simple; + profiles[1] = vlProfileMpeg2Main; + + return 0; +} + +unsigned int vlGetMaxEntryPoints +( + struct vlScreen *screen +) +{ + assert(screen); + + return vlEntryPointCount; +} + +int vlQueryEntryPoints +( + struct vlScreen *screen, + enum vlProfile profile, + enum vlEntryPoint *entry_points +) +{ + assert(screen); + assert(entry_points); + + entry_points[0] = vlEntryPointIDCT; + entry_points[1] = vlEntryPointMC; + entry_points[2] = vlEntryPointCSC; + + return 0; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_screen.h b/src/gallium/state_trackers/g3dvl/vl_screen.h new file mode 100644 index 00000000000..98f3d429b61 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_screen.h @@ -0,0 +1,63 @@ +#ifndef vl_screen_h +#define vl_screen_h + +#include "vl_types.h" + +struct pipe_screen; + +#ifdef VL_INTERNAL +struct vlScreen +{ + struct vlDisplay *display; + unsigned int ordinal; + struct pipe_screen *pscreen; +}; +#endif + +int vlCreateScreen +( + struct vlDisplay *display, + int screen, + struct pipe_screen *pscreen, + struct vlScreen **vl_screen +); + +int vlDestroyScreen +( + struct vlScreen *screen +); + +struct vlDisplay* vlGetDisplay +( + struct vlScreen *screen +); + +struct pipe_screen* vlGetPipeScreen +( + struct vlScreen *screen +); + +unsigned int vlGetMaxProfiles +( + struct vlScreen *screen +); + +int vlQueryProfiles +( + struct vlScreen *screen, + enum vlProfile *profiles +); + +unsigned int vlGetMaxEntryPoints +( + struct vlScreen *screen +); + +int vlQueryEntryPoints +( + struct vlScreen *screen, + enum vlProfile profile, + enum vlEntryPoint *entry_points +); + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_shader_build.c b/src/gallium/state_trackers/g3dvl/vl_shader_build.c new file mode 100644 index 00000000000..51f1721a332 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_shader_build.c @@ -0,0 +1,215 @@ +#include "vl_shader_build.h" +#include <assert.h> +#include <tgsi/tgsi_parse.h> +#include <tgsi/tgsi_build.h> + +struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last) +{ + struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + + decl.Declaration.File = TGSI_FILE_INPUT; + decl.Declaration.Semantic = 1; + decl.Semantic.SemanticName = name; + decl.Semantic.SemanticIndex = index; + decl.DeclarationRange.First = first; + decl.DeclarationRange.Last = last; + + return decl; +} + +struct tgsi_full_declaration vl_decl_interpolated_input +( + unsigned int name, + unsigned int index, + unsigned int first, + unsigned int last, + int interpolation +) +{ + struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + + assert + ( + interpolation == TGSI_INTERPOLATE_CONSTANT || + interpolation == TGSI_INTERPOLATE_LINEAR || + interpolation == TGSI_INTERPOLATE_PERSPECTIVE + ); + + decl.Declaration.File = TGSI_FILE_INPUT; + decl.Declaration.Semantic = 1; + decl.Semantic.SemanticName = name; + decl.Semantic.SemanticIndex = index; + decl.Declaration.Interpolate = interpolation;; + decl.DeclarationRange.First = first; + decl.DeclarationRange.Last = last; + + return decl; +} + +struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last) +{ + struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + + decl.Declaration.File = TGSI_FILE_CONSTANT; + decl.Declaration.Semantic = 1; + decl.Semantic.SemanticName = name; + decl.Semantic.SemanticIndex = index; + decl.DeclarationRange.First = first; + decl.DeclarationRange.Last = last; + + return decl; +} + +struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last) +{ + struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + + decl.Declaration.File = TGSI_FILE_OUTPUT; + decl.Declaration.Semantic = 1; + decl.Semantic.SemanticName = name; + decl.Semantic.SemanticIndex = index; + decl.DeclarationRange.First = first; + decl.DeclarationRange.Last = last; + + return decl; +} + +struct tgsi_full_declaration vl_decl_temps(unsigned int first, unsigned int last) +{ + struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_TEMPORARY; + decl.DeclarationRange.First = first; + decl.DeclarationRange.Last = last; + + return decl; +} + +struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last) +{ + struct tgsi_full_declaration decl = tgsi_default_full_declaration(); + + decl = tgsi_default_full_declaration(); + decl.Declaration.File = TGSI_FILE_SAMPLER; + decl.DeclarationRange.First = first; + decl.DeclarationRange.Last = last; + + return decl; +} + +struct tgsi_full_instruction vl_inst2 +( + int opcode, + enum tgsi_file_type dst_file, + unsigned int dst_index, + enum tgsi_file_type src_file, + unsigned int src_index +) +{ + struct tgsi_full_instruction inst = tgsi_default_full_instruction(); + + inst.Instruction.Opcode = opcode; + inst.Instruction.NumDstRegs = 1; + inst.FullDstRegisters[0].DstRegister.File = dst_file; + inst.FullDstRegisters[0].DstRegister.Index = dst_index; + inst.Instruction.NumSrcRegs = 1; + inst.FullSrcRegisters[0].SrcRegister.File = src_file; + inst.FullSrcRegisters[0].SrcRegister.Index = src_index; + + return inst; +} + +struct tgsi_full_instruction vl_inst3 +( + int opcode, + enum tgsi_file_type dst_file, + unsigned int dst_index, + enum tgsi_file_type src1_file, + unsigned int src1_index, + enum tgsi_file_type src2_file, + unsigned int src2_index +) +{ + struct tgsi_full_instruction inst = tgsi_default_full_instruction(); + + inst.Instruction.Opcode = opcode; + inst.Instruction.NumDstRegs = 1; + inst.FullDstRegisters[0].DstRegister.File = dst_file; + inst.FullDstRegisters[0].DstRegister.Index = dst_index; + inst.Instruction.NumSrcRegs = 2; + inst.FullSrcRegisters[0].SrcRegister.File = src1_file; + inst.FullSrcRegisters[0].SrcRegister.Index = src1_index; + inst.FullSrcRegisters[1].SrcRegister.File = src2_file; + inst.FullSrcRegisters[1].SrcRegister.Index = src2_index; + + return inst; +} + +struct tgsi_full_instruction vl_tex +( + int tex, + enum tgsi_file_type dst_file, + unsigned int dst_index, + enum tgsi_file_type src1_file, + unsigned int src1_index, + enum tgsi_file_type src2_file, + unsigned int src2_index +) +{ + struct tgsi_full_instruction inst = tgsi_default_full_instruction(); + + inst.Instruction.Opcode = TGSI_OPCODE_TEX; + inst.Instruction.NumDstRegs = 1; + inst.FullDstRegisters[0].DstRegister.File = dst_file; + inst.FullDstRegisters[0].DstRegister.Index = dst_index; + inst.Instruction.NumSrcRegs = 2; + inst.InstructionExtTexture.Texture = tex; + inst.FullSrcRegisters[0].SrcRegister.File = src1_file; + inst.FullSrcRegisters[0].SrcRegister.Index = src1_index; + inst.FullSrcRegisters[1].SrcRegister.File = src2_file; + inst.FullSrcRegisters[1].SrcRegister.Index = src2_index; + + return inst; +} + +struct tgsi_full_instruction vl_inst4 +( + int opcode, + enum tgsi_file_type dst_file, + unsigned int dst_index, + enum tgsi_file_type src1_file, + unsigned int src1_index, + enum tgsi_file_type src2_file, + unsigned int src2_index, + enum tgsi_file_type src3_file, + unsigned int src3_index +) +{ + struct tgsi_full_instruction inst = tgsi_default_full_instruction(); + + inst.Instruction.Opcode = opcode; + inst.Instruction.NumDstRegs = 1; + inst.FullDstRegisters[0].DstRegister.File = dst_file; + inst.FullDstRegisters[0].DstRegister.Index = dst_index; + inst.Instruction.NumSrcRegs = 3; + inst.FullSrcRegisters[0].SrcRegister.File = src1_file; + inst.FullSrcRegisters[0].SrcRegister.Index = src1_index; + inst.FullSrcRegisters[1].SrcRegister.File = src2_file; + inst.FullSrcRegisters[1].SrcRegister.Index = src2_index; + inst.FullSrcRegisters[2].SrcRegister.File = src3_file; + inst.FullSrcRegisters[2].SrcRegister.Index = src3_index; + + return inst; +} + +struct tgsi_full_instruction vl_end(void) +{ + struct tgsi_full_instruction inst = tgsi_default_full_instruction(); + + inst.Instruction.Opcode = TGSI_OPCODE_END; + inst.Instruction.NumDstRegs = 0; + inst.Instruction.NumSrcRegs = 0; + + return inst; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_shader_build.h b/src/gallium/state_trackers/g3dvl/vl_shader_build.h new file mode 100644 index 00000000000..dc615cb1566 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_shader_build.h @@ -0,0 +1,61 @@ +#ifndef vl_shader_build_h +#define vl_shader_build_h + +#include <pipe/p_shader_tokens.h> + +struct tgsi_full_declaration vl_decl_input(unsigned int name, unsigned int index, unsigned int first, unsigned int last); +struct tgsi_full_declaration vl_decl_interpolated_input +( + unsigned int name, + unsigned int index, + unsigned int first, + unsigned int last, + int interpolation +); +struct tgsi_full_declaration vl_decl_constants(unsigned int name, unsigned int index, unsigned int first, unsigned int last); +struct tgsi_full_declaration vl_decl_output(unsigned int name, unsigned int index, unsigned int first, unsigned int last); +struct tgsi_full_declaration vl_decl_temps(unsigned int first, unsigned int last); +struct tgsi_full_declaration vl_decl_samplers(unsigned int first, unsigned int last); +struct tgsi_full_instruction vl_inst2 +( + int opcode, + enum tgsi_file_type dst_file, + unsigned int dst_index, + enum tgsi_file_type src_file, + unsigned int src_index +); +struct tgsi_full_instruction vl_inst3 +( + int opcode, + enum tgsi_file_type dst_file, + unsigned int dst_index, + enum tgsi_file_type src1_file, + unsigned int src1_index, + enum tgsi_file_type src2_file, + unsigned int src2_index +); +struct tgsi_full_instruction vl_tex +( + int tex, + enum tgsi_file_type dst_file, + unsigned int dst_index, + enum tgsi_file_type src1_file, + unsigned int src1_index, + enum tgsi_file_type src2_file, + unsigned int src2_index +); +struct tgsi_full_instruction vl_inst4 +( + int opcode, + enum tgsi_file_type dst_file, + unsigned int dst_index, + enum tgsi_file_type src1_file, + unsigned int src1_index, + enum tgsi_file_type src2_file, + unsigned int src2_index, + enum tgsi_file_type src3_file, + unsigned int src3_index +); +struct tgsi_full_instruction vl_end(void); + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.c b/src/gallium/state_trackers/g3dvl/vl_surface.c new file mode 100644 index 00000000000..92388f7978d --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_surface.c @@ -0,0 +1,243 @@ +#define VL_INTERNAL +#include "vl_surface.h" +#include <assert.h> +#include <string.h> +#include <pipe/p_screen.h> +#include <pipe/p_state.h> +#include <pipe/p_inlines.h> +#include <util/u_memory.h> +#include <vl_winsys.h> +#include "vl_screen.h" +#include "vl_context.h" +#include "vl_render.h" +#include "vl_csc.h" +#include "vl_util.h" + +int vlCreateSurface +( + struct vlScreen *screen, + unsigned int width, + unsigned int height, + enum vlFormat format, + struct vlSurface **surface +) +{ + struct vlSurface *sfc; + struct pipe_texture template; + + assert(screen); + assert(surface); + + sfc = CALLOC_STRUCT(vlSurface); + + if (!sfc) + return 1; + + sfc->screen = screen; + sfc->width = width; + sfc->height = height; + sfc->format = format; + + memset(&template, 0, sizeof(struct pipe_texture)); + template.target = PIPE_TEXTURE_2D; + template.format = PIPE_FORMAT_A8R8G8B8_UNORM; + template.last_level = 0; + template.width[0] = vlRoundUpPOT(sfc->width); + template.height[0] = vlRoundUpPOT(sfc->height); + template.depth[0] = 1; + template.compressed = 0; + pf_get_block(template.format, &template.block); + template.tex_usage = PIPE_TEXTURE_USAGE_SAMPLER | PIPE_TEXTURE_USAGE_RENDER_TARGET; + + sfc->texture = vlGetPipeScreen(screen)->texture_create(vlGetPipeScreen(screen), &template); + + if (!sfc->texture) + { + FREE(sfc); + return 1; + } + + *surface = sfc; + + return 0; +} + +int vlDestroySurface +( + struct vlSurface *surface +) +{ + assert(surface); + + pipe_texture_reference(&surface->texture, NULL); + FREE(surface); + + return 0; +} + +int vlRenderMacroBlocksMpeg2 +( + struct vlMpeg2MacroBlockBatch *batch, + struct vlSurface *surface +) +{ + assert(batch); + assert(surface); + assert(surface->context); + + surface->context->render->vlBegin(surface->context->render); + + surface->context->render->vlRenderMacroBlocksMpeg2 + ( + surface->context->render, + batch, + surface + ); + + surface->context->render->vlEnd(surface->context->render); + + return 0; +} + +int vlPutPicture +( + struct vlSurface *surface, + vlNativeDrawable drawable, + int srcx, + int srcy, + int srcw, + int srch, + int destx, + int desty, + int destw, + int desth, + int drawable_w, + int drawable_h, + enum vlPictureType picture_type +) +{ + struct vlCSC *csc; + struct pipe_context *pipe; + + assert(surface); + assert(surface->context); + + surface->context->render->vlFlush(surface->context->render); + + csc = surface->context->csc; + pipe = surface->context->pipe; + + csc->vlResizeFrameBuffer(csc, drawable_w, drawable_h); + + csc->vlBegin(csc); + + csc->vlPutPicture + ( + csc, + surface, + srcx, + srcy, + srcw, + srch, + destx, + desty, + destw, + desth, + picture_type + ); + + csc->vlEnd(csc); + + pipe->flush(pipe, PIPE_FLUSH_RENDER_CACHE, &surface->disp_fence); + + bind_pipe_drawable(pipe, drawable); + + pipe->screen->flush_frontbuffer + ( + pipe->screen, + csc->vlGetFrameBuffer(csc), + pipe->priv + ); + + return 0; +} + +int vlSurfaceGetStatus +( + struct vlSurface *surface, + enum vlResourceStatus *status +) +{ + assert(surface); + assert(surface->context); + assert(status); + + if (surface->render_fence && !surface->context->pipe->screen->fence_signalled(surface->context->pipe->screen, surface->render_fence, 0)) + { + *status = vlResourceStatusRendering; + return 0; + } + + if (surface->disp_fence && !surface->context->pipe->screen->fence_signalled(surface->context->pipe->screen, surface->disp_fence, 0)) + { + *status = vlResourceStatusDisplaying; + return 0; + } + + *status = vlResourceStatusFree; + + return 0; +} + +int vlSurfaceFlush +( + struct vlSurface *surface +) +{ + assert(surface); + assert(surface->context); + + surface->context->render->vlFlush(surface->context->render); + + return 0; +} + +int vlSurfaceSync +( + struct vlSurface *surface +) +{ + assert(surface); + assert(surface->context); + assert(surface->render_fence); + + surface->context->pipe->screen->fence_finish(surface->context->pipe->screen, surface->render_fence, 0); + + return 0; +} + +struct vlScreen* vlSurfaceGetScreen +( + struct vlSurface *surface +) +{ + assert(surface); + + return surface->screen; +} + +struct vlContext* vlBindToContext +( + struct vlSurface *surface, + struct vlContext *context +) +{ + struct vlContext *old; + + assert(surface); + + old = surface->context; + surface->context = context; + + return old; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_surface.h b/src/gallium/state_trackers/g3dvl/vl_surface.h new file mode 100644 index 00000000000..133e1515ef3 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_surface.h @@ -0,0 +1,86 @@ +#ifndef vl_surface_h +#define vl_surface_h + +#include "vl_types.h" + +#ifdef VL_INTERNAL +struct pipe_texture; + +struct vlSurface +{ + struct vlScreen *screen; + struct vlContext *context; + unsigned int width; + unsigned int height; + enum vlFormat format; + struct pipe_texture *texture; + struct pipe_fence_handle *render_fence; + struct pipe_fence_handle *disp_fence; +}; +#endif + +int vlCreateSurface +( + struct vlScreen *screen, + unsigned int width, + unsigned int height, + enum vlFormat format, + struct vlSurface **surface +); + +int vlDestroySurface +( + struct vlSurface *surface +); + +int vlRenderMacroBlocksMpeg2 +( + struct vlMpeg2MacroBlockBatch *batch, + struct vlSurface *surface +); + +int vlPutPicture +( + struct vlSurface *surface, + vlNativeDrawable drawable, + int srcx, + int srcy, + int srcw, + int srch, + int destx, + int desty, + int destw, + int desth, + int drawable_w, + int drawable_h, + enum vlPictureType picture_type +); + +int vlSurfaceGetStatus +( + struct vlSurface *surface, + enum vlResourceStatus *status +); + +int vlSurfaceFlush +( + struct vlSurface *surface +); + +int vlSurfaceSync +( + struct vlSurface *surface +); + +struct vlScreen* vlSurfaceGetScreen +( + struct vlSurface *surface +); + +struct vlContext* vlBindToContext +( + struct vlSurface *surface, + struct vlContext *context +); + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_types.h b/src/gallium/state_trackers/g3dvl/vl_types.h new file mode 100644 index 00000000000..274e1f74377 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_types.h @@ -0,0 +1,115 @@ +#ifndef vl_types_h +#define vl_types_h + +#if 1 /*#ifdef X11*/ +#include <X11/Xlib.h> + +typedef Display* vlNativeDisplay; +typedef Drawable vlNativeDrawable; +#endif + +struct vlDisplay; +struct vlScreen; +struct vlContext; +struct vlSurface; + +enum vlResourceStatus +{ + vlResourceStatusFree, + vlResourceStatusRendering, + vlResourceStatusDisplaying +}; + +enum vlProfile +{ + vlProfileMpeg2Simple, + vlProfileMpeg2Main, + + vlProfileCount +}; + +enum vlEntryPoint +{ + vlEntryPointIDCT, + vlEntryPointMC, + vlEntryPointCSC, + + vlEntryPointCount +}; + +enum vlFormat +{ + vlFormatYCbCr420, + vlFormatYCbCr422, + vlFormatYCbCr444 +}; + +enum vlPictureType +{ + vlPictureTypeTopField, + vlPictureTypeBottomField, + vlPictureTypeFrame +}; + +enum vlMotionType +{ + vlMotionTypeField, + vlMotionTypeFrame, + vlMotionTypeDualPrime, + vlMotionType16x8 +}; + +enum vlFieldOrder +{ + vlFieldOrderFirst, + vlFieldOrderSecond +}; + +enum vlDCTType +{ + vlDCTTypeFrameCoded, + vlDCTTypeFieldCoded +}; + +struct vlVertex2f +{ + float x, y; +}; + +struct vlVertex4f +{ + float x, y, z, w; +}; + +enum vlMacroBlockType +{ + vlMacroBlockTypeIntra, + vlMacroBlockTypeFwdPredicted, + vlMacroBlockTypeBkwdPredicted, + vlMacroBlockTypeBiPredicted, + + vlNumMacroBlockTypes +}; + +struct vlMpeg2MacroBlock +{ + unsigned int mbx, mby; + enum vlMacroBlockType mb_type; + enum vlMotionType mo_type; + enum vlDCTType dct_type; + int PMV[2][2][2]; + unsigned int cbp; + short *blocks; +}; + +struct vlMpeg2MacroBlockBatch +{ + struct vlSurface *past_surface; + struct vlSurface *future_surface; + enum vlPictureType picture_type; + enum vlFieldOrder field_order; + unsigned int num_macroblocks; + struct vlMpeg2MacroBlock *macroblocks; +}; + +#endif diff --git a/src/gallium/state_trackers/g3dvl/vl_util.c b/src/gallium/state_trackers/g3dvl/vl_util.c new file mode 100644 index 00000000000..50aa9af66f2 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_util.c @@ -0,0 +1,16 @@ +#include "vl_util.h" +#include <assert.h> + +unsigned int vlRoundUpPOT(unsigned int x) +{ + unsigned int i; + + assert(x > 0); + + --x; + + for (i = 1; i < sizeof(unsigned int) * 8; i <<= 1) + x |= x >> i; + + return x + 1; +} diff --git a/src/gallium/state_trackers/g3dvl/vl_util.h b/src/gallium/state_trackers/g3dvl/vl_util.h new file mode 100644 index 00000000000..bc98e79df47 --- /dev/null +++ b/src/gallium/state_trackers/g3dvl/vl_util.h @@ -0,0 +1,6 @@ +#ifndef vl_util_h +#define vl_util_h + +unsigned int vlRoundUpPOT(unsigned int x); + +#endif diff --git a/src/gallium/state_trackers/glx/Makefile b/src/gallium/state_trackers/glx/Makefile new file mode 100644 index 00000000000..f779035763e --- /dev/null +++ b/src/gallium/state_trackers/glx/Makefile @@ -0,0 +1,25 @@ +TOP = ../../../.. +include $(TOP)/configs/current + + +SUBDIRS = xlib + + +default: subdirs + + +subdirs: + @for dir in $(SUBDIRS) ; do \ + if [ -d $$dir ] ; then \ + (cd $$dir && $(MAKE)) || exit 1 ; \ + fi \ + done + + +clean: + rm -f `find . -name \*.[oa]` + rm -f `find . -name depend` + + +# Dummy install target +install: diff --git a/src/gallium/state_trackers/glx/dri/dri_context.c b/src/gallium/state_trackers/glx/dri/dri_context.c new file mode 100644 index 00000000000..9424e18bee3 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri/dri_context.c @@ -0,0 +1,168 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_winsys.h" + +#include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" +#include "pipe/p_context.h" + +#include "util/u_memory.h" + + +GLboolean +dri_create_context(const __GLcontextModes *visual, + __DRIcontextPrivate *cPriv, + void *sharedContextPrivate) +{ + __DRIscreenPrivate *sPriv = cPriv->driScreenPriv; + struct dri_screen *screen = dri_screen(sPriv); + struct dri_context *ctx = NULL; + struct st_context *st_share = NULL; + + if (sharedContextPrivate) { + st_share = ((struct dri_context *) sharedContextPrivate)->st; + } + + ctx = CALLOC_STRUCT(dri_context); + if (ctx == NULL) + goto fail; + + cPriv->driverPrivate = ctx; + ctx->cPriv = cPriv; + ctx->sPriv = sPriv; + + driParseConfigFiles(&ctx->optionCache, + &screen->optionCache, + sPriv->myNum, + "dri"); + + ctx->pipe = screen->pipe_screen->create_context(screen->pipe_screen, + screen->pipe_winsys, + hw_winsys ); + if (ctx->pipe == NULL) + goto fail; + + ctx->pipe->priv = ctx; /* I guess */ + + ctx->st = st_create_context(ctx->pipe, visual, st_share); + if (ctx->st == NULL) + goto fail; + + dri_init_extensions( ctx ); + + return GL_TRUE; + +fail: + if (ctx && ctx->st) + st_destroy_context( ctx->st ); + + if (ctx && ctx->pipe) + ctx->pipe->destroy( ctx->pipe ); + + FREE(ctx); + return FALSE; +} + + +void +dri_destroy_context(__DRIcontextPrivate *cPriv) +{ + struct dri_context *ctx = dri_context(cPriv); + struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); + struct pipe_winsys *winsys = screen->winsys; + + /* No particular reason to wait for command completion before + * destroying a context, but it is probably worthwhile flushing it + * to avoid having to add code elsewhere to cope with flushing a + * partially destroyed context. + */ + st_flush(ctx->st); + + if (screen->dummyContext == ctx) + screen->dummyContext = NULL; + + /* Also frees ctx->pipe? + */ + st_destroy_context(ctx->st); + + FREE(ctx); +} + + +GLboolean +dri_unbind_context(__DRIcontextPrivate *cPriv) +{ + struct dri_context *ctx = dri_context(cPriv); + st_flush(ctx->st, PIPE_FLUSH_RENDER_CACHE, NULL); + /* XXX make_current(NULL)? */ + return GL_TRUE; +} + + +GLboolean +dri_make_current(__DRIcontextPrivate *cPriv, + __DRIdrawablePrivate *driDrawPriv, + __DRIdrawablePrivate *driReadPriv) +{ + if (cPriv) { + struct dri_context *ctx = dri_context(cPriv); + struct dri_screen *screen = dri_screen(cPriv->driScreenPriv); + struct dri_drawable *draw = dri_drawable(driDrawPriv); + struct dri_drawable *read = dri_drawable(driReadPriv); + + /* This is for situations in which we need a rendering context but + * there may not be any currently bound. + */ + screen->dummyContext = ctx; + + st_make_current( ctx->st, + draw->stfb, + read->stfb ); + + ctx->dPriv = driDrawPriv; + + /* Update window sizes if necessary: + */ + if (draw->stamp != driDrawPriv->lastStamp) { + dri_update_window_size( draw ); + } + + if (read->stamp != driReadPriv->lastStamp) { + dri_update_window_size( read ); + } + + } + else { + st_make_current(NULL, NULL, NULL); + } + + return GL_TRUE; +} diff --git a/src/gallium/state_trackers/glx/dri/dri_context.h b/src/gallium/state_trackers/glx/dri/dri_context.h new file mode 100644 index 00000000000..4e6a305abb0 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri/dri_context.h @@ -0,0 +1,95 @@ +/************************************************************************** + * + * Copyright (C) 2009 VMware, Inc. All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef DRI_CONTEXT_H +#define DRI_CONTEXT_H + +#include "pipe/p_compiler.h" +#include "drm.h" +#include "dri_util.h" + + +struct pipe_context; +struct pipe_fence; +struct st_context; + + +struct dri_context +{ + __DRIcontextPrivate *cPriv; + __DRIdrawablePrivate *dPriv; + + struct st_context *st; + struct pipe_context *pipe; + + boolean locked; + + /** + * Configuration cache + */ + driOptionCache optionCache; +}; + + +static INLINE struct dri_context * +dri_context(__DRIcontextPrivate *driContextPriv) +{ + return (struct dri_context *) driContextPriv->driverPrivate; +} + +/*********************************************************************** + * dri_context.c + */ +void +dri_destroy_context(__DRIcontextPrivate * driContextPriv); + +boolean +dri_unbind_context(__DRIcontextPrivate * driContextPriv); + +boolean +dri_make_current(__DRIcontextPrivate * driContextPriv, + __DRIdrawablePrivate * driDrawPriv, + __DRIdrawablePrivate * driReadPriv); + +boolean +dri_create_context(const __GLcontextModes * visual, + __DRIcontextPrivate * driContextPriv, + void *sharedContextPrivate); + + + +/*********************************************************************** + * dri_lock.c + */ +void dri_lock_hardware( struct dri_context *context, + struct dri_drawable *drawable ); + +void dri_unlock_hardware( struct dri_context *dri ); +boolean dri_is_locked( struct dri_context *dri ); + + + +#endif diff --git a/src/gallium/state_trackers/glx/dri/dri_drawable.c b/src/gallium/state_trackers/glx/dri/dri_drawable.c new file mode 100644 index 00000000000..b712acda88e --- /dev/null +++ b/src/gallium/state_trackers/glx/dri/dri_drawable.c @@ -0,0 +1,363 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "dri_screen.h" +#include "dri_context.h" +#include "dri_swapbuffers.h" + +#include "pipe/p_context.h" +#include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_cb_fbo.h" + + +static void +blit_swapbuffers(__DRIdrawablePrivate *dPriv, + __DRIcontextPrivate *cPriv, + struct pipe_surface *src, + const drm_clip_rect_t *rect) +{ + struct dri_screen *screen = dri_screen(dPriv->driScreenPriv); + struct dri_drawable *fb = dri_drawable(dPriv); + struct dri_context *context = dri_context(cPriv); + + const int nbox = dPriv->numClipRects; + const drm_clip_rect_t *pbox = dPriv->pClipRects; + + struct pipe_surface *dest = fb->front_surface; + const int backWidth = fb->stfb->Base.Width; + const int backHeight = fb->stfb->Base.Height; + int i; + + for (i = 0; i < nbox; i++, pbox++) { + drm_clip_rect_t box; + drm_clip_rect_t sbox; + + if (pbox->x1 > pbox->x2 || + pbox->y1 > pbox->y2 || + (pbox->x2 - pbox->x1) > dest->width || + (pbox->y2 - pbox->y1) > dest->height) + continue; + + box = *pbox; + + if (rect) { + drm_clip_rect_t rrect; + + rrect.x1 = dPriv->x + rect->x1; + rrect.y1 = (dPriv->h - rect->y1 - rect->y2) + dPriv->y; + rrect.x2 = rect->x2 + rrect.x1; + rrect.y2 = rect->y2 + rrect.y1; + if (rrect.x1 > box.x1) + box.x1 = rrect.x1; + if (rrect.y1 > box.y1) + box.y1 = rrect.y1; + if (rrect.x2 < box.x2) + box.x2 = rrect.x2; + if (rrect.y2 < box.y2) + box.y2 = rrect.y2; + + if (box.x1 > box.x2 || box.y1 > box.y2) + continue; + } + + /* restrict blit to size of actually rendered area */ + if (box.x2 - box.x1 > backWidth) + box.x2 = backWidth + box.x1; + if (box.y2 - box.y1 > backHeight) + box.y2 = backHeight + box.y1; + + debug_printf("%s: box %d,%d-%d,%d\n", __FUNCTION__, + box.x1, box.y1, box.x2, box.y2); + + sbox.x1 = box.x1 - dPriv->x; + sbox.y1 = box.y1 - dPriv->y; + + ctx->st->pipe->surface_copy( ctx->st->pipe, + FALSE, + dest, + box.x1, box.y1, + src, + sbox.x1, sbox.y1, + box.x2 - box.x1, + box.y2 - box.y1 ); + } +} + +/** + * Display a colorbuffer surface in an X window. + * Used for SwapBuffers and flushing front buffer rendering. + * + * \param dPriv the window/drawable to display into + * \param surf the surface to display + * \param rect optional subrect of surface to display (may be NULL). + */ +static void +dri_display_surface(__DRIdrawablePrivate *dPriv, + struct pipe_surface *source, + const drm_clip_rect_t *rect) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct dri_screen *screen = dri_screen(dPriv->driScreenPriv); + struct dri_context *context = screen->dummy_context; + struct pipe_winsys *winsys = screen->winsys; + + if (!context) + return; + + if (drawable->last_swap_fence) { + winsys->fence_finish( winsys, + drawable->last_swap_fence, + 0 ); + + winsys->fence_reference( winsys, + &drawable->last_swap_fence, + NULL ); + } + + drawable->last_swap_fence = drawable->first_swap_fence; + drawable->first_swap_fence = NULL; + + /* Call lock_hardware to update dPriv cliprects. + */ + dri_lock_hardware(context, drawable); + { + if (dPriv->numClipRects) { + blit_swapbuffers( context, dPriv, source, rect ); + } + } + dri_unlock_hardware(context); + + if (drawble->stamp != drawable->dPriv->lastStamp) { + dri_update_window_size( dpriv ); + } +} + + + +/** + * This will be called a drawable is known to have moved/resized. + */ +void +dri_update_window_size(__DRIdrawablePrivate *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + st_resize_framebuffer(drawable->stfb, dPriv->w, dPriv->h); + drawable->stamp = dPriv->lastStamp; +} + + + +void +dri_swap_buffers(__DRIdrawablePrivate * dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_surface *back_surf; + + assert(drawable); + assert(drawable->stfb); + + back_surf = st_get_framebuffer_surface(drawable->stfb, + ST_SURFACE_BACK_LEFT); + if (back_surf) { + st_notify_swapbuffers(drawable->stfb); + dri_display_surface(dPriv, back_surf, NULL); + st_notify_swapbuffers_complete(drawable->stfb); + } +} + + +/** + * Called via glXCopySubBufferMESA() to copy a subrect of the back + * buffer to the front buffer/screen. + */ +void +dri_copy_sub_buffer(__DRIdrawablePrivate * dPriv, int x, int y, int w, int h) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + struct pipe_surface *back_surf; + + assert(drawable); + assert(drawable->stfb); + + back_surf = st_get_framebuffer_surface(drawable->stfb, + ST_SURFACE_BACK_LEFT); + if (back_surf) { + drm_clip_rect_t rect; + rect.x1 = x; + rect.y1 = y; + rect.x2 = w; + rect.y2 = h; + + st_notify_swapbuffers(drawable->stfb); + dri_display_surface(dPriv, back_surf, &rect); + } +} + + + +/* + * The state tracker keeps track of whether the fake frontbuffer has + * been touched by any rendering since the last time we copied its + * contents to the real frontbuffer. Our task is easy: + */ +static void +dri_flush_frontbuffer( struct pipe_winsys *winsys, + struct pipe_surface *surf, + void *context_private) +{ + struct dri_context *dri = (struct dri_context *) context_private; + __DRIdrawablePrivate *dPriv = dri->driDrawable; + + dri_display_surface(dPriv, surf, NULL); +} + + + +/* Need to create a surface which wraps the front surface to support + * client-side swapbuffers. + */ +static void +dri_create_front_surface(struct dri_screen *screen, + struct pipe_winsys *winsys, + unsigned handle) +{ + struct pipe_screen *pipe_screen = screen->pipe_screen; + struct pipe_texture *texture; + struct pipe_texture templat; + struct pipe_surface *surface; + struct pipe_buffer *buffer; + unsigned pitch; + + assert(screen->front.cpp == 4); + +// buffer = dri_buffer_from_handle(screen->winsys, +// "front", handle); + + if (!buffer) + return; + + screen->front.buffer = dri_bo(buffer); + + memset(&templat, 0, sizeof(templat)); + templat.tex_usage |= PIPE_TEXTURE_USAGE_DISPLAY_TARGET; + templat.target = PIPE_TEXTURE_2D; + templat.last_level = 0; + templat.depth[0] = 1; + templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templat.width[0] = screen->front.width; + templat.height[0] = screen->front.height; + pf_get_block(templat.format, &templat.block); + pitch = screen->front.pitch; + + texture = pipe_screen->texture_blanket(pipe_screen, + &templat, + &pitch, + buffer); + + /* Unref the buffer we don't need it anyways */ + pipe_buffer_reference(screen, &buffer, NULL); + + surface = pipe_screen->get_tex_surface(pipe_screen, + texture, + 0, + 0, + 0, + PIPE_BUFFER_USAGE_GPU_WRITE); + + screen->front.texture = texture; + screen->front.surface = surface; +} + +/** + * This is called when we need to set up GL rendering to a new X window. + */ +static boolean +dri_create_buffer(__DRIscreenPrivate *sPriv, + __DRIdrawablePrivate *dPriv, + const __GLcontextModes *visual, + boolean isPixmap) +{ + enum pipe_format colorFormat, depthFormat, stencilFormat; + struct dri_drawable *drawable; + + if (isPixmap) + goto fail; /* not implemented */ + + drawable = CALLOC_STRUCT(dri_drawable); + if (drawable == NULL) + goto fail; + + /* XXX: todo: use the pipe_screen queries to figure out which + * render targets are supportable. + */ + 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) { + if (visual->stencilBits == 8) + depthFormat = PIPE_FORMAT_S8Z24_UNORM; + else + depthFormat = PIPE_FORMAT_X8Z24_UNORM; + } + + drawable->stfb = st_create_framebuffer(visual, + colorFormat, + depthFormat, + dPriv->w, + dPriv->h, + (void*) drawable); + if (drawable->stfb == NULL) + goto fail; + + dPriv->driverPrivate = (void *) drawable; + return GL_TRUE; + +fail: + FREE(drawable); + return GL_FALSE; +} + +static void +dri_destroy_buffer(__DRIdrawablePrivate *dPriv) +{ + struct dri_drawable *drawable = dri_drawable(dPriv); + + /* No particular need to wait on fences before dereferencing them: + */ + winsys->fence_reference( winsys, &ctx->last_swap_fence, NULL ); + winsys->fence_reference( winsys, &ctx->first_swap_fence, NULL ); + + st_unreference_framebuffer(drawable->stfb); + + FREE(drawable); +} + diff --git a/src/gallium/state_trackers/glx/dri/dri_drawable.h b/src/gallium/state_trackers/glx/dri/dri_drawable.h new file mode 100644 index 00000000000..1001bb8c578 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri/dri_drawable.h @@ -0,0 +1,73 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef DRI_DRAWABLE_H +#define DRI_DRAWABLE_H + +#include "pipe/p_compiler.h" + +struct pipe_surface; +struct pipe_fence; +struct st_framebuffer; + + +struct dri_drawable +{ + __DRIdrawablePrivate *dPriv; + unsigned stamp; + + struct pipe_fence *last_swap_fence; + struct pipe_fence *first_swap_fence; + + struct st_framebuffer *stfb; +}; + + +static INLINE struct dri_drawable * +dri_drawable(__DRIdrawablePrivate * driDrawPriv) +{ + return (struct dri_drawable *) driDrawPriv->driverPrivate; +} + + +/*********************************************************************** + * dri_drawable.c + */ + +void +dri_swap_buffers(__DRIdrawablePrivate * dPriv); + +void +dri_copy_sub_buffer(__DRIdrawablePrivate * dPriv, + int x, int y, + int w, int h); + +void +dri_update_window_size(__DRIdrawablePrivate *dPriv); + + +#endif diff --git a/src/gallium/state_trackers/glx/dri/dri_extensions.c b/src/gallium/state_trackers/glx/dri/dri_extensions.c new file mode 100644 index 00000000000..126faf76014 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri/dri_extensions.c @@ -0,0 +1,108 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + + + +#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" + + +/** + * Extension strings exported by the driver. + */ +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} +}; + + + +void +dri_init_extensions( void ) +{ + /* The card_extensions list should be pruned according to the + * capabilities of the pipe_screen. This is actually something + * that can/should be done inside st_create_context(). + */ + driInitExtensions( ctx->st->ctx, card_extensions, GL_TRUE ); +} diff --git a/src/gallium/state_trackers/glx/dri/dri_lock.c b/src/gallium/state_trackers/glx/dri/dri_lock.c new file mode 100644 index 00000000000..b272ab55f34 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri/dri_lock.c @@ -0,0 +1,90 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "pipe/p_thread.h" +#include "dri_context.h" +#include "xf86drm.h" + +pipe_static_mutex( lockMutex ); + +static void +dri_contended_lock(struct dri_context *ctx) +{ + __DRIdrawablePrivate *dPriv = ctx->dPriv; + __DRIcontextPrivate *cPriv = ctx->cPriv; + __DRIscreenPrivate *sPriv = cPriv->driScreenPriv; + + drmGetLock(sPriv->fd, cPriv->hHWContext, 0); + + /* Perform round trip communication with server (including dropping + * and retaking the above lock) to update window dimensions: + */ + if (dPriv) + DRI_VALIDATE_DRAWABLE_INFO(sPriv, dPriv); +} + + +/* Lock the hardware and validate our state. + */ +void dri_lock_hardware( struct dri_context *ctx ) +{ + __DRIcontextPrivate *cPriv = ctx->cPriv; + __DRIscreenPrivate *sPriv = cPriv->driScreenPriv; + char __ret = 0; + + pipe_mutex_lock(lockMutex); + assert(!ctx->locked); + + DRM_CAS((drmLock *) &sPriv->pSAREA->lock, + cPriv->hHWContext, + (DRM_LOCK_HELD | cPriv->hHWContext), + __ret); + + if (__ret) + dri_contended_lock( ctx ); + + ctx->locked = TRUE; +} + + +/* Unlock the hardware using the global current context + */ +void dri_unlock_hardware( struct dri_context *ctx ) +{ + __DRIcontextPrivate *cPriv = ctx->cPriv; + __DRIscreenPrivate *sPriv = cPriv->driScreenPriv; + + assert(ctx->locked); + ctx->locked = FALSE; + + DRM_UNLOCK(sPriv->fd, + (drmLock *) &sPriv->pSAREA->lock, + cPriv->hHWContext); + + pipe_mutex_unlock(lockMutex); +} diff --git a/src/gallium/state_trackers/glx/dri/dri_screen.c b/src/gallium/state_trackers/glx/dri/dri_screen.c new file mode 100644 index 00000000000..f7119b949a3 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri/dri_screen.c @@ -0,0 +1,255 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "utils.h" +#include "vblank.h" +#include "xmlpool.h" + +#include "dri_context.h" +#include "dri_screen.h" + +#include "pipe/p_context.h" +#include "pipe/p_screen.h" +#include "pipe/p_inlines.h" +#include "state_tracker/st_public.h" +#include "state_tracker/st_cb_fbo.h" + + +PUBLIC const char __driConfigOptions[] = + DRI_CONF_BEGIN DRI_CONF_SECTION_PERFORMANCE + DRI_CONF_FTHROTTLE_MODE(DRI_CONF_FTHROTTLE_IRQS) + DRI_CONF_VBLANK_MODE(DRI_CONF_VBLANK_DEF_INTERVAL_0) + DRI_CONF_SECTION_END DRI_CONF_SECTION_QUALITY +// DRI_CONF_FORCE_S3TC_ENABLE(false) + DRI_CONF_ALLOW_LARGE_TEXTURES(1) + DRI_CONF_SECTION_END DRI_CONF_END; + +const uint __driNConfigOptions = 3; + +static PFNGLXCREATECONTEXTMODES create_context_modes = NULL; + +extern const struct dri_extension card_extensions[]; + + + +static const __DRIextension *driScreenExtensions[] = { + &driReadDrawableExtension, + &driCopySubBufferExtension.base, + &driSwapControlExtension.base, + &driFrameTrackingExtension.base, + &driMediaStreamCounterExtension.base, + NULL +}; + + + + +static const char * +dri_get_name( struct pipe_winsys *winsys ) +{ + return "dri"; +} + + + +static void +dri_destroy_screen(__DRIscreenPrivate * sPriv) +{ + struct dri_screen *screen = dri_screen(sPriv); + + screen->pipe_screen->destroy( screen->pipe_screen ); + screen->pipe_winsys->destroy( screen->pipe_winsys ); + FREE(screen); + sPriv->private = NULL; +} + + +/** + * Get information about previous buffer swaps. + */ +static int +dri_get_swap_info(__DRIdrawablePrivate * dPriv, + __DRIswapInfo * sInfo) +{ + if (dPriv == NULL || + dPriv->driverPrivate == NULL || + sInfo == NULL) + return -1; + else + return 0; +} + +static const __DRIconfig ** +dri_fill_in_modes(__DRIscreenPrivate *psp, + unsigned pixel_bits ) +{ + __DRIconfig **configs; + __GLcontextModes *m; + unsigned num_modes; + uint8_t depth_bits_array[3]; + uint8_t stencil_bits_array[3]; + uint8_t msaa_samples_array[1]; + unsigned depth_buffer_factor; + unsigned back_buffer_factor; + GLenum fb_format; + GLenum fb_type; + int i; + + static const GLenum back_buffer_modes[] = { + GLX_NONE, GLX_SWAP_UNDEFINED_OML + }; + + depth_bits_array[0] = 0; + depth_bits_array[1] = depth_bits; + depth_bits_array[2] = depth_bits; + + stencil_bits_array[0] = 0; /* no depth or stencil */ + stencil_bits_array[1] = 0; /* z24x8 */ + stencil_bits_array[2] = 8; /* z24s8 */ + + msaa_samples_array[0] = 0; + + depth_buffer_factor = 3; + back_buffer_factor = 1; + + num_modes = depth_buffer_factor * back_buffer_factor * 4; + + if (pixel_bits == 16) { + fb_format = GL_RGB; + fb_type = GL_UNSIGNED_SHORT_5_6_5; + } + else { + fb_format = GL_BGRA; + fb_type = GL_UNSIGNED_INT_8_8_8_8_REV; + } + + configs = driCreateConfigs(fb_format, fb_type, + depth_bits_array, + stencil_bits_array, depth_buffer_factor, + back_buffer_modes, back_buffer_factor, + msaa_samples_array, 1); + if (configs == NULL) { + debug_printf("%s: driCreateConfigs failed\n", __FUNCTION__); + return NULL; + } + + return configs; +} + + + +/* This is the driver specific part of the createNewScreen entry point. + * + * Returns the __GLcontextModes supported by this driver. + */ +static const __DRIconfig **dri_init_screen(__DRIscreenPrivate *sPriv) +{ + static const __DRIversion ddx_expected = { 1, 6, 0 }; /* hw query */ + static const __DRIversion dri_expected = { 4, 0, 0 }; + static const __DRIversion drm_expected = { 1, 5, 0 }; /* hw query */ + struct dri_screen *screen; + + if (!driCheckDriDdxDrmVersions2("dri", + &sPriv->dri_version, &dri_expected, + &sPriv->ddx_version, &ddx_expected, + &sPriv->drm_version, &drm_expected)) { + return NULL; + } + + /* Set up dispatch table to cope with all known extensions: + */ + driInitExtensions( NULL, card_extensions, GL_FALSE ); + + + screen = CALLOC_STRUCT(dri_screen); + if (!screen) + goto fail; + + screen->sPriv = sPriv; + sPriv->private = (void *) screen; + + + /* Search the registered winsys' for one that likes this sPriv. + * This is required in situations where multiple devices speak to + * the same DDX and are built into the same binary. + * + * Note that cases like Intel i915 vs i965 doesn't fall into this + * category because they are built into separate binaries. + * + * Nonetheless, it's healthy to keep that level of detail out of + * this state_tracker. + */ + for (i = 0; + i < dri1_winsys_count && + screen->st_winsys == NULL; + i++) + { + screen->dri_winsys = + dri_winsys[i]->check_dri_privates( sPriv->pDevPriv, + sPriv->pSAREA + /* versions, etc?? */)); + } + + + driParseOptionInfo(&screen->optionCache, + __driConfigOptions, + __driNConfigOptions); + + + /* Plug our info back into the __DRIscreenPrivate: + */ + sPriv->private = (void *) screen; + sPriv->extensions = driScreenExtensions; + + return dri_fill_in_modes(sPriv, + dri_priv->cpp * 8, + 24, + 8, + 1); +fail: + return NULL; +} + + + +const struct __DriverAPIRec driDriverAPI = { + .InitScreen = dri_init_screen, + .DestroyScreen = dri_destroy_screen, + .CreateContext = dri_create_context, + .DestroyContext = dri_destroy_context, + .CreateBuffer = dri_create_buffer, + .DestroyBuffer = dri_destroy_buffer, + .SwapBuffers = dri_swap_buffers, + .MakeCurrent = dri_make_current, + .UnbindContext = dri_unbind_context, + .GetSwapInfo = dri_get_swap_info, + .GetDrawableMSC = driDrawableGetMSC32, + .WaitForMSC = driWaitForMSC32, + .CopySubBuffer = dri_copy_sub_buffer, + + //.InitScreen2 = dri_init_screen2, +}; diff --git a/src/gallium/state_trackers/glx/dri/dri_screen.h b/src/gallium/state_trackers/glx/dri/dri_screen.h new file mode 100644 index 00000000000..12ed86d22a9 --- /dev/null +++ b/src/gallium/state_trackers/glx/dri/dri_screen.h @@ -0,0 +1,83 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef DRI_SCREEN_H +#define DRI_SCREEN_H + +#include "dri_util.h" +#include "xmlconfig.h" + +#include "pipe/p_compiler.h" + +struct dri_screen +{ + __DRIScreenPrivate *sPriv; + struct pipe_winsys *pipe_winsys; + struct pipe_screen *pipe_screen; + + struct { + /* Need a pipe_surface pointer to do client-side swapbuffers: + */ + unsigned long buffer_handle; + struct pipe_surface *surface; + struct pipe_texture *texture; + + int pitch; /* row stride, in bytes */ + int width; + int height; + int size; + int cpp; /* for front and back buffers */ + } front; + + int deviceID; + int drmMinor; + + + /** + * Configuration cache with default values for all contexts + */ + driOptionCache optionCache; + + /** + * Temporary(?) context to use for SwapBuffers or other situations in + * which we need a rendering context, but none is currently bound. + */ + struct dri_context *dummyContext; +}; + + + +/** cast wrapper */ +static INLINE struct dri_screen * +dri_screen(__DRIscreenPrivate *sPriv) +{ + return (struct dri_screen *) sPriv->private; +} + + + +#endif diff --git a/src/gallium/state_trackers/glx/xlib/Makefile b/src/gallium/state_trackers/glx/xlib/Makefile new file mode 100644 index 00000000000..1b63db1f0ea --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/Makefile @@ -0,0 +1,25 @@ +TOP = ../../../../.. +include $(TOP)/configs/current + +LIBNAME = xlib + + +DRIVER_INCLUDES = \ + -I$(TOP)/include \ + -I$(TOP)/src/mesa \ + -I$(TOP)/src/mesa/main \ + -I$(TOP)/src/gallium/include \ + -I$(TOP)/src/gallium/drivers \ + -I$(TOP)/src/gallium/auxiliary + +C_SOURCES = \ + glxapi.c \ + fakeglx.c \ + fakeglx_fonts.c \ + xm_api.c + + +include ../../../Makefile.template + +symlinks: + diff --git a/src/gallium/state_trackers/glx/xlib/SConscript b/src/gallium/state_trackers/glx/xlib/SConscript new file mode 100644 index 00000000000..14cdad69cbe --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/SConscript @@ -0,0 +1,26 @@ +####################################################################### +# SConscript for xlib state_tracker + +Import('*') + +if env['platform'] == 'linux' \ + and 'mesa' in env['statetrackers'] \ + and ('softpipe' or 'i915simple' or 'trace') in env['drivers'] \ + and not env['dri']: + + env = env.Clone() + + env.Append(CPPPATH = [ + '#/src/mesa', + '#/src/mesa/main', + ]) + + st_xlib = env.ConvenienceLibrary( + target = 'st_xlib', + source = [ 'glxapi.c', + 'fakeglx.c', + 'fakeglx_fonts.c', + 'xm_api.c', + ] + ) + Export('st_xlib') diff --git a/src/gallium/state_trackers/glx/xlib/fakeglx.c b/src/gallium/state_trackers/glx/xlib/fakeglx.c new file mode 100644 index 00000000000..65e7048188e --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/fakeglx.c @@ -0,0 +1,2743 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * This is an emulation of the GLX API which allows Mesa/GLX-based programs + * to run on X servers which do not have the real GLX extension. + * + * Thanks to the contributors: + * + * Initial version: Philip Brown ([email protected]) + * Better glXGetConfig() support: Armin Liebchen ([email protected]) + * Further visual-handling refinements: Wolfram Gloger + * ([email protected]). + * + * Notes: + * Don't be fooled, stereo isn't supported yet. + */ + + + +#include "glxapi.h" +#include "xm_api.h" +#include "context.h" +#include "config.h" +#include "macros.h" +#include "imports.h" +#include "version.h" +#include "fakeglx.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_public.h" + + +/* This indicates the client-side GLX API and GLX encoder version. */ +#define CLIENT_MAJOR_VERSION 1 +#define CLIENT_MINOR_VERSION 4 /* but don't have 1.3's pbuffers, etc yet */ + +/* This indicates the server-side GLX decoder version. + * GLX 1.4 indicates OpenGL 1.3 support + */ +#define SERVER_MAJOR_VERSION 1 +#define SERVER_MINOR_VERSION 4 + +/* This is appended onto the glXGetClient/ServerString version strings. */ +#define MESA_GLX_VERSION "Mesa " MESA_VERSION_STRING + +/* Who implemented this GLX? */ +#define VENDOR "Brian Paul" + +#define EXTENSIONS \ + "GLX_MESA_copy_sub_buffer " \ + "GLX_MESA_pixmap_colormap " \ + "GLX_MESA_release_buffers " \ + "GLX_ARB_get_proc_address " \ + "GLX_EXT_texture_from_pixmap " \ + "GLX_EXT_visual_info " \ + "GLX_EXT_visual_rating " \ + /*"GLX_SGI_video_sync "*/ \ + "GLX_SGIX_fbconfig " \ + "GLX_SGIX_pbuffer " + +/* + * Our fake GLX context will contain a "real" GLX context and an XMesa context. + * + * Note that a pointer to a __GLXcontext is a pointer to a fake_glx_context, + * and vice versa. + * + * We really just need this structure in order to make the libGL functions + * glXGetCurrentContext(), glXGetCurrentDrawable() and glXGetCurrentDisplay() + * work correctly. + */ +struct fake_glx_context { + __GLXcontext glxContext; /* this MUST be first! */ + XMesaContext xmesaContext; +}; + + + +/**********************************************************************/ +/*** GLX Visual Code ***/ +/**********************************************************************/ + +#define DONT_CARE -1 + + +static XMesaVisual *VisualTable = NULL; +static int NumVisuals = 0; + + + +/* Macro to handle c_class vs class field name in XVisualInfo struct */ +#if defined(__cplusplus) || defined(c_plusplus) +#define CLASS c_class +#else +#define CLASS class +#endif + + + +/* + * Test if the given XVisualInfo is usable for Mesa rendering. + */ +static GLboolean +is_usable_visual( XVisualInfo *vinfo ) +{ + switch (vinfo->CLASS) { + case StaticGray: + case GrayScale: + /* Any StaticGray/GrayScale visual works in RGB or CI mode */ + return GL_TRUE; + case StaticColor: + case PseudoColor: + /* Any StaticColor/PseudoColor visual of at least 4 bits */ + if (vinfo->depth>=4) { + return GL_TRUE; + } + else { + return GL_FALSE; + } + case TrueColor: + case DirectColor: + /* Any depth of TrueColor or DirectColor works in RGB mode */ + return GL_TRUE; + default: + /* This should never happen */ + return GL_FALSE; + } +} + + +/* + * Given an XVisualInfo and RGB, Double, and Depth buffer flags, save the + * configuration in our list of GLX visuals. + */ +static XMesaVisual +save_glx_visual( Display *dpy, XVisualInfo *vinfo, + GLboolean rgbFlag, GLboolean alphaFlag, GLboolean dbFlag, + GLboolean stereoFlag, + GLint depth_size, GLint stencil_size, + GLint accumRedSize, GLint accumGreenSize, + GLint accumBlueSize, GLint accumAlphaSize, + GLint level, GLint numAuxBuffers ) +{ + GLboolean ximageFlag = GL_TRUE; + XMesaVisual xmvis; + GLint i; + GLboolean comparePointers; + + if (dbFlag) { + /* Check if the MESA_BACK_BUFFER env var is set */ + char *backbuffer = _mesa_getenv("MESA_BACK_BUFFER"); + if (backbuffer) { + if (backbuffer[0]=='p' || backbuffer[0]=='P') { + ximageFlag = GL_FALSE; + } + else if (backbuffer[0]=='x' || backbuffer[0]=='X') { + ximageFlag = GL_TRUE; + } + else { + _mesa_warning(NULL, "Mesa: invalid value for MESA_BACK_BUFFER environment variable, using an XImage."); + } + } + } + + if (stereoFlag) { + /* stereo not supported */ + return NULL; + } + + if (stencil_size > 0 && depth_size > 0) + depth_size = 24; + + /* Comparing IDs uses less memory but sometimes fails. */ + /* XXX revisit this after 3.0 is finished. */ + if (_mesa_getenv("MESA_GLX_VISUAL_HACK")) + comparePointers = GL_TRUE; + else + comparePointers = GL_FALSE; + + /* Force the visual to have an alpha channel */ + if (rgbFlag && _mesa_getenv("MESA_GLX_FORCE_ALPHA")) + alphaFlag = GL_TRUE; + + /* First check if a matching visual is already in the list */ + for (i=0; i<NumVisuals; i++) { + XMesaVisual v = VisualTable[i]; + if (v->display == dpy + && v->mesa_visual.level == level + && v->mesa_visual.numAuxBuffers == numAuxBuffers + && v->ximage_flag == ximageFlag + && v->mesa_visual.rgbMode == rgbFlag + && v->mesa_visual.doubleBufferMode == dbFlag + && v->mesa_visual.stereoMode == stereoFlag + && (v->mesa_visual.alphaBits > 0) == alphaFlag + && (v->mesa_visual.depthBits >= depth_size || depth_size == 0) + && (v->mesa_visual.stencilBits >= stencil_size || stencil_size == 0) + && (v->mesa_visual.accumRedBits >= accumRedSize || accumRedSize == 0) + && (v->mesa_visual.accumGreenBits >= accumGreenSize || accumGreenSize == 0) + && (v->mesa_visual.accumBlueBits >= accumBlueSize || accumBlueSize == 0) + && (v->mesa_visual.accumAlphaBits >= accumAlphaSize || accumAlphaSize == 0)) { + /* now either compare XVisualInfo pointers or visual IDs */ + if ((!comparePointers && v->visinfo->visualid == vinfo->visualid) + || (comparePointers && v->vishandle == vinfo)) { + return v; + } + } + } + + /* Create a new visual and add it to the list. */ + + xmvis = XMesaCreateVisual( dpy, vinfo, rgbFlag, alphaFlag, dbFlag, + stereoFlag, ximageFlag, + depth_size, stencil_size, + accumRedSize, accumBlueSize, + accumBlueSize, accumAlphaSize, 0, level, + GLX_NONE_EXT ); + if (xmvis) { + /* Save a copy of the pointer now so we can find this visual again + * if we need to search for it in find_glx_visual(). + */ + xmvis->vishandle = vinfo; + /* Allocate more space for additional visual */ + VisualTable = (XMesaVisual *) _mesa_realloc( VisualTable, + sizeof(XMesaVisual) * NumVisuals, + sizeof(XMesaVisual) * (NumVisuals + 1)); + /* add xmvis to the list */ + VisualTable[NumVisuals] = xmvis; + NumVisuals++; + /* XXX minor hack, because XMesaCreateVisual doesn't support an + * aux buffers parameter. + */ + xmvis->mesa_visual.numAuxBuffers = numAuxBuffers; + } + return xmvis; +} + + +/** + * Return the default number of bits for the Z buffer. + * If defined, use the MESA_GLX_DEPTH_BITS env var value. + * Otherwise, use the DEFAULT_SOFTWARE_DEPTH_BITS constant. + * XXX probably do the same thing for stencil, accum, etc. + */ +static GLint +default_depth_bits(void) +{ + int zBits; + const char *zEnv = _mesa_getenv("MESA_GLX_DEPTH_BITS"); + if (zEnv) + zBits = _mesa_atoi(zEnv); + else + zBits = DEFAULT_SOFTWARE_DEPTH_BITS; + return zBits; +} + +static GLint +default_alpha_bits(void) +{ + int aBits; + const char *aEnv = _mesa_getenv("MESA_GLX_ALPHA_BITS"); + if (aEnv) + aBits = _mesa_atoi(aEnv); + else + aBits = 0; + return aBits; +} + +static GLint +default_accum_bits(void) +{ + return 16; +} + + + +/* + * Create a GLX visual from a regular XVisualInfo. + * This is called when Fake GLX is given an XVisualInfo which wasn't + * returned by glXChooseVisual. Since this is the first time we're + * considering this visual we'll take a guess at reasonable values + * for depth buffer size, stencil size, accum size, etc. + * This is the best we can do with a client-side emulation of GLX. + */ +static XMesaVisual +create_glx_visual( Display *dpy, XVisualInfo *visinfo ) +{ + GLint zBits = default_depth_bits(); + GLint accBits = default_accum_bits(); + GLboolean alphaFlag = default_alpha_bits() > 0; + + if (is_usable_visual( visinfo )) { + /* Configure this visual as RGB, double-buffered, depth-buffered. */ + /* This is surely wrong for some people's needs but what else */ + /* can be done? They should use glXChooseVisual(). */ + return save_glx_visual( dpy, visinfo, + GL_TRUE, /* rgb */ + alphaFlag, /* alpha */ + GL_TRUE, /* double */ + GL_FALSE, /* stereo */ + zBits, + STENCIL_BITS, + accBits, /* r */ + accBits, /* g */ + accBits, /* b */ + accBits, /* a */ + 0, /* level */ + 0 /* numAux */ + ); + } + else { + _mesa_warning(NULL, "Mesa: error in glXCreateContext: bad visual\n"); + return NULL; + } +} + + + +/* + * Find the GLX visual associated with an XVisualInfo. + */ +static XMesaVisual +find_glx_visual( Display *dpy, XVisualInfo *vinfo ) +{ + int i; + + /* try to match visual id */ + for (i=0;i<NumVisuals;i++) { + if (VisualTable[i]->display==dpy + && VisualTable[i]->visinfo->visualid == vinfo->visualid) { + return VisualTable[i]; + } + } + + /* if that fails, try to match pointers */ + for (i=0;i<NumVisuals;i++) { + if (VisualTable[i]->display==dpy && VisualTable[i]->vishandle==vinfo) { + return VisualTable[i]; + } + } + + return NULL; +} + + + + + + +/** + * Try to get an X visual which matches the given arguments. + */ +static XVisualInfo * +get_visual( Display *dpy, int scr, unsigned int depth, int xclass ) +{ + XVisualInfo temp, *vis; + long mask; + int n; + unsigned int default_depth; + int default_class; + + mask = VisualScreenMask | VisualDepthMask | VisualClassMask; + temp.screen = scr; + temp.depth = depth; + temp.CLASS = xclass; + + default_depth = DefaultDepth(dpy,scr); + default_class = DefaultVisual(dpy,scr)->CLASS; + + if (depth==default_depth && xclass==default_class) { + /* try to get root window's visual */ + temp.visualid = DefaultVisual(dpy,scr)->visualid; + mask |= VisualIDMask; + } + + vis = XGetVisualInfo( dpy, mask, &temp, &n ); + + /* In case bits/pixel > 24, make sure color channels are still <=8 bits. + * An SGI Infinite Reality system, for example, can have 30bpp pixels: + * 10 bits per color channel. Mesa's limited to a max of 8 bits/channel. + */ + if (vis && depth > 24 && (xclass==TrueColor || xclass==DirectColor)) { + if (_mesa_bitcount((GLuint) vis->red_mask ) <= 8 && + _mesa_bitcount((GLuint) vis->green_mask) <= 8 && + _mesa_bitcount((GLuint) vis->blue_mask ) <= 8) { + return vis; + } + else { + XFree((void *) vis); + return NULL; + } + } + + return vis; +} + + + +/* + * Retrieve the value of the given environment variable and find + * the X visual which matches it. + * Input: dpy - the display + * screen - the screen number + * varname - the name of the environment variable + * Return: an XVisualInfo pointer to NULL if error. + */ +static XVisualInfo * +get_env_visual(Display *dpy, int scr, const char *varname) +{ + char value[100], type[100]; + int depth, xclass = -1; + XVisualInfo *vis; + + if (!_mesa_getenv( varname )) { + return NULL; + } + + _mesa_strncpy( value, _mesa_getenv(varname), 100 ); + value[99] = 0; + + sscanf( value, "%s %d", type, &depth ); + + if (_mesa_strcmp(type,"TrueColor")==0) xclass = TrueColor; + else if (_mesa_strcmp(type,"DirectColor")==0) xclass = DirectColor; + else if (_mesa_strcmp(type,"PseudoColor")==0) xclass = PseudoColor; + else if (_mesa_strcmp(type,"StaticColor")==0) xclass = StaticColor; + else if (_mesa_strcmp(type,"GrayScale")==0) xclass = GrayScale; + else if (_mesa_strcmp(type,"StaticGray")==0) xclass = StaticGray; + + if (xclass>-1 && depth>0) { + vis = get_visual( dpy, scr, depth, xclass ); + if (vis) { + return vis; + } + } + + _mesa_warning(NULL, "GLX unable to find visual class=%s, depth=%d.", + type, depth); + + return NULL; +} + + + +/* + * Select an X visual which satisfies the RGBA flag and minimum depth. + * Input: dpy, + * screen - X display and screen number + * min_depth - minimum visual depth + * preferred_class - preferred GLX visual class or DONT_CARE + * Return: pointer to an XVisualInfo or NULL. + */ +static XVisualInfo * +choose_x_visual( Display *dpy, int screen, int min_depth, + int preferred_class ) +{ + XVisualInfo *vis; + int xclass, visclass = 0; + int depth; + + /* First see if the MESA_RGB_VISUAL env var is defined */ + vis = get_env_visual( dpy, screen, "MESA_RGB_VISUAL" ); + if (vis) { + return vis; + } + /* Otherwise, search for a suitable visual */ + if (preferred_class==DONT_CARE) { + for (xclass=0;xclass<6;xclass++) { + switch (xclass) { + case 0: visclass = TrueColor; break; + case 1: visclass = DirectColor; break; + case 2: visclass = PseudoColor; break; + case 3: visclass = StaticColor; break; + case 4: visclass = GrayScale; break; + case 5: visclass = StaticGray; break; + } + if (min_depth==0) { + /* start with shallowest */ + for (depth=0;depth<=32;depth++) { + if (visclass==TrueColor && depth==8) { + /* Special case: try to get 8-bit PseudoColor before */ + /* 8-bit TrueColor */ + vis = get_visual( dpy, screen, 8, PseudoColor ); + if (vis) { + return vis; + } + } + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + else { + /* start with deepest */ + for (depth=32;depth>=min_depth;depth--) { + if (visclass==TrueColor && depth==8) { + /* Special case: try to get 8-bit PseudoColor before */ + /* 8-bit TrueColor */ + vis = get_visual( dpy, screen, 8, PseudoColor ); + if (vis) { + return vis; + } + } + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + } + } + else { + /* search for a specific visual class */ + switch (preferred_class) { + case GLX_TRUE_COLOR_EXT: visclass = TrueColor; break; + case GLX_DIRECT_COLOR_EXT: visclass = DirectColor; break; + case GLX_PSEUDO_COLOR_EXT: visclass = PseudoColor; break; + case GLX_STATIC_COLOR_EXT: visclass = StaticColor; break; + case GLX_GRAY_SCALE_EXT: visclass = GrayScale; break; + case GLX_STATIC_GRAY_EXT: visclass = StaticGray; break; + default: return NULL; + } + if (min_depth==0) { + /* start with shallowest */ + for (depth=0;depth<=32;depth++) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + else { + /* start with deepest */ + for (depth=32;depth>=min_depth;depth--) { + vis = get_visual( dpy, screen, depth, visclass ); + if (vis) { + return vis; + } + } + } + } + + /* didn't find a visual */ + return NULL; +} + + + + +/**********************************************************************/ +/*** Display-related functions ***/ +/**********************************************************************/ + + +/** + * Free all XMesaVisuals which are associated with the given display. + */ +static void +destroy_visuals_on_display(Display *dpy) +{ + int i; + for (i = 0; i < NumVisuals; i++) { + if (VisualTable[i]->display == dpy) { + /* remove this visual */ + int j; + free(VisualTable[i]); + for (j = i; j < NumVisuals - 1; j++) + VisualTable[j] = VisualTable[j + 1]; + NumVisuals--; + } + } +} + + +/** + * Called from XCloseDisplay() to let us free our display-related data. + */ +static int +close_display_callback(Display *dpy, XExtCodes *codes) +{ + destroy_visuals_on_display(dpy); + xmesa_destroy_buffers_on_display(dpy); + return 0; +} + + +/** + * Look for the named extension on given display and return a pointer + * to the _XExtension data, or NULL if extension not found. + */ +static _XExtension * +lookup_extension(Display *dpy, const char *extName) +{ + _XExtension *ext; + for (ext = dpy->ext_procs; ext; ext = ext->next) { + if (ext->name && strcmp(ext->name, extName) == 0) { + return ext; + } + } + return NULL; +} + + +/** + * Whenever we're given a new Display pointer, call this function to + * register our close_display_callback function. + */ +static void +register_with_display(Display *dpy) +{ + const char *extName = "MesaGLX"; + _XExtension *ext; + + ext = lookup_extension(dpy, extName); + if (!ext) { + XExtCodes *c = XAddExtension(dpy); + ext = dpy->ext_procs; /* new extension is at head of list */ + assert(c->extension == ext->codes.extension); + ext->name = _mesa_strdup(extName); + ext->close_display = close_display_callback; + } +} + + +/**********************************************************************/ +/*** Begin Fake GLX API Functions ***/ +/**********************************************************************/ + + +/** + * Helper used by glXChooseVisual and glXChooseFBConfig. + * The fbConfig parameter must be GL_FALSE for the former and GL_TRUE for + * the later. + * In either case, the attribute list is terminated with the value 'None'. + */ +static XMesaVisual +choose_visual( Display *dpy, int screen, const int *list, GLboolean fbConfig ) +{ + const GLboolean rgbModeDefault = fbConfig; + const int *parselist; + XVisualInfo *vis; + int min_ci = 0; + int min_red=0, min_green=0, min_blue=0; + GLboolean rgb_flag = rgbModeDefault; + GLboolean alpha_flag = GL_FALSE; + GLboolean double_flag = GL_FALSE; + GLboolean stereo_flag = GL_FALSE; + GLint depth_size = 0; + GLint stencil_size = 0; + GLint accumRedSize = 0; + GLint accumGreenSize = 0; + GLint accumBlueSize = 0; + GLint accumAlphaSize = 0; + int level = 0; + int visual_type = DONT_CARE; + int trans_type = DONT_CARE; + int trans_value = DONT_CARE; + GLint caveat = DONT_CARE; + XMesaVisual xmvis = NULL; + int desiredVisualID = -1; + int numAux = 0; + + parselist = list; + + while (*parselist) { + + switch (*parselist) { + case GLX_USE_GL: + if (fbConfig) { + /* invalid token */ + return NULL; + } + else { + /* skip */ + parselist++; + } + break; + case GLX_BUFFER_SIZE: + parselist++; + min_ci = *parselist++; + break; + case GLX_LEVEL: + parselist++; + level = *parselist++; + break; + case GLX_RGBA: + if (fbConfig) { + /* invalid token */ + return NULL; + } + else { + rgb_flag = GL_TRUE; + parselist++; + } + break; + case GLX_DOUBLEBUFFER: + parselist++; + if (fbConfig) { + double_flag = *parselist++; + } + else { + double_flag = GL_TRUE; + } + break; + case GLX_STEREO: + parselist++; + if (fbConfig) { + stereo_flag = *parselist++; + } + else { + stereo_flag = GL_TRUE; + } + break; + case GLX_AUX_BUFFERS: + parselist++; + numAux = *parselist++; + if (numAux > MAX_AUX_BUFFERS) + return NULL; + break; + case GLX_RED_SIZE: + parselist++; + min_red = *parselist++; + break; + case GLX_GREEN_SIZE: + parselist++; + min_green = *parselist++; + break; + case GLX_BLUE_SIZE: + parselist++; + min_blue = *parselist++; + break; + case GLX_ALPHA_SIZE: + parselist++; + { + GLint size = *parselist++; + alpha_flag = size ? GL_TRUE : GL_FALSE; + } + break; + case GLX_DEPTH_SIZE: + parselist++; + depth_size = *parselist++; + break; + case GLX_STENCIL_SIZE: + parselist++; + stencil_size = *parselist++; + break; + case GLX_ACCUM_RED_SIZE: + parselist++; + { + GLint size = *parselist++; + accumRedSize = MAX2( accumRedSize, size ); + } + break; + case GLX_ACCUM_GREEN_SIZE: + parselist++; + { + GLint size = *parselist++; + accumGreenSize = MAX2( accumGreenSize, size ); + } + break; + case GLX_ACCUM_BLUE_SIZE: + parselist++; + { + GLint size = *parselist++; + accumBlueSize = MAX2( accumBlueSize, size ); + } + break; + case GLX_ACCUM_ALPHA_SIZE: + parselist++; + { + GLint size = *parselist++; + accumAlphaSize = MAX2( accumAlphaSize, size ); + } + break; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_X_VISUAL_TYPE_EXT: + parselist++; + visual_type = *parselist++; + break; + case GLX_TRANSPARENT_TYPE_EXT: + parselist++; + trans_type = *parselist++; + break; + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + parselist++; + trans_value = *parselist++; + break; + case GLX_TRANSPARENT_RED_VALUE_EXT: + case GLX_TRANSPARENT_GREEN_VALUE_EXT: + case GLX_TRANSPARENT_BLUE_VALUE_EXT: + case GLX_TRANSPARENT_ALPHA_VALUE_EXT: + /* ignore */ + parselist++; + parselist++; + break; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_VISUAL_CAVEAT_EXT: + parselist++; + caveat = *parselist++; /* ignored for now */ + break; + + /* + * GLX_ARB_multisample + */ + case GLX_SAMPLE_BUFFERS_ARB: + /* ms not supported */ + return NULL; + case GLX_SAMPLES_ARB: + /* ms not supported */ + return NULL; + + /* + * FBConfig attribs. + */ + case GLX_RENDER_TYPE: + if (!fbConfig) + return NULL; + parselist++; + if (*parselist == GLX_RGBA_BIT) { + rgb_flag = GL_TRUE; + } + else if (*parselist == GLX_COLOR_INDEX_BIT) { + rgb_flag = GL_FALSE; + } + else if (*parselist == 0) { + rgb_flag = GL_TRUE; + } + parselist++; + break; + case GLX_DRAWABLE_TYPE: + if (!fbConfig) + return NULL; + parselist++; + if (*parselist & ~(GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT)) { + return NULL; /* bad bit */ + } + parselist++; + break; + case GLX_FBCONFIG_ID: + if (!fbConfig) + return NULL; + parselist++; + desiredVisualID = *parselist++; + break; + case GLX_X_RENDERABLE: + if (!fbConfig) + return NULL; + parselist += 2; + /* ignore */ + break; + +#ifdef GLX_EXT_texture_from_pixmap + case GLX_BIND_TO_TEXTURE_RGB_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + parselist++; /*skip*/ + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + parselist++; + if (*parselist & ~(GLX_TEXTURE_1D_BIT_EXT | + GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT)) { + /* invalid bit */ + return NULL; + } + break; + case GLX_Y_INVERTED_EXT: + parselist++; /*skip*/ + break; +#endif + + case None: + /* end of list */ + break; + + default: + /* undefined attribute */ + _mesa_warning(NULL, "unexpected attrib 0x%x in choose_visual()", + *parselist); + return NULL; + } + } + + (void) caveat; + + + /* + * Since we're only simulating the GLX extension this function will never + * find any real GL visuals. Instead, all we can do is try to find an RGB + * or CI visual of appropriate depth. Other requested attributes such as + * double buffering, depth buffer, etc. will be associated with the X + * visual and stored in the VisualTable[]. + */ + if (desiredVisualID != -1) { + /* try to get a specific visual, by visualID */ + XVisualInfo temp; + int n; + temp.visualid = desiredVisualID; + temp.screen = screen; + vis = XGetVisualInfo(dpy, VisualIDMask | VisualScreenMask, &temp, &n); + if (vis) { + /* give the visual some useful GLX attributes */ + double_flag = GL_TRUE; + rgb_flag = GL_TRUE; + depth_size = default_depth_bits(); + stencil_size = STENCIL_BITS; + /* XXX accum??? */ + } + } + else if (level==0) { + /* normal color planes */ + /* Get an RGB visual */ + int min_rgb = min_red + min_green + min_blue; + if (min_rgb>1 && min_rgb<8) { + /* a special case to be sure we can get a monochrome visual */ + min_rgb = 1; + } + vis = choose_x_visual( dpy, screen, min_rgb, visual_type ); + } + else { + _mesa_warning(NULL, "overlay not supported"); + return NULL; + } + + if (vis) { + /* Note: we're not exactly obeying the glXChooseVisual rules here. + * When GLX_DEPTH_SIZE = 1 is specified we're supposed to choose the + * largest depth buffer size, which is 32bits/value. Instead, we + * return 16 to maintain performance with earlier versions of Mesa. + */ + if (stencil_size > 0) + depth_size = 24; /* if Z and stencil, always use 24+8 format */ + else if (depth_size > 24) + depth_size = 32; + else if (depth_size > 16) + depth_size = 24; + else if (depth_size > 0) { + depth_size = default_depth_bits(); + } + + if (!alpha_flag) { + alpha_flag = default_alpha_bits() > 0; + } + + /* we only support one size of stencil and accum buffers. */ + if (stencil_size > 0) + stencil_size = STENCIL_BITS; + + if (accumRedSize > 0 || + accumGreenSize > 0 || + accumBlueSize > 0 || + accumAlphaSize > 0) { + + accumRedSize = + accumGreenSize = + accumBlueSize = default_accum_bits(); + + accumAlphaSize = alpha_flag ? accumRedSize : 0; + } + + xmvis = save_glx_visual( dpy, vis, rgb_flag, alpha_flag, double_flag, + stereo_flag, depth_size, stencil_size, + accumRedSize, accumGreenSize, + accumBlueSize, accumAlphaSize, level, numAux ); + } + + return xmvis; +} + + +static XVisualInfo * +Fake_glXChooseVisual( Display *dpy, int screen, int *list ) +{ + XMesaVisual xmvis; + + /* register ourselves as an extension on this display */ + register_with_display(dpy); + + xmvis = choose_visual(dpy, screen, list, GL_FALSE); + if (xmvis) { + /* create a new vishandle - the cached one may be stale */ + xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo)); + if (xmvis->vishandle) { + _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); + } + return xmvis->vishandle; + } + else + return NULL; +} + + +static GLXContext +Fake_glXCreateContext( Display *dpy, XVisualInfo *visinfo, + GLXContext share_list, Bool direct ) +{ + XMesaVisual xmvis; + struct fake_glx_context *glxCtx; + struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list; + + if (!dpy || !visinfo) + return 0; + + glxCtx = CALLOC_STRUCT(fake_glx_context); + if (!glxCtx) + return 0; + + /* deallocate unused windows/buffers */ +#if 0 + XMesaGarbageCollect(); +#endif + + xmvis = find_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* This visual wasn't found with glXChooseVisual() */ + xmvis = create_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* unusable visual */ + _mesa_free(glxCtx); + return NULL; + } + } + + glxCtx->xmesaContext = XMesaCreateContext(xmvis, + shareCtx ? shareCtx->xmesaContext : NULL); + if (!glxCtx->xmesaContext) { + _mesa_free(glxCtx); + return NULL; + } + + glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.currentDpy = dpy; + glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ + + assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + + return (GLXContext) glxCtx; +} + + +/* XXX these may have to be removed due to thread-safety issues. */ +static GLXContext MakeCurrent_PrevContext = 0; +static GLXDrawable MakeCurrent_PrevDrawable = 0; +static GLXDrawable MakeCurrent_PrevReadable = 0; +static XMesaBuffer MakeCurrent_PrevDrawBuffer = 0; +static XMesaBuffer MakeCurrent_PrevReadBuffer = 0; + + +/* GLX 1.3 and later */ +static Bool +Fake_glXMakeContextCurrent( Display *dpy, GLXDrawable draw, + GLXDrawable read, GLXContext ctx ) +{ + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + static boolean firsttime = 1, no_rast = 0; + + if (firsttime) { + no_rast = getenv("SP_NO_RAST") != NULL; + firsttime = 0; + } + + + if (ctx && draw && read) { + XMesaBuffer drawBuffer, readBuffer; + XMesaContext xmctx = glxCtx->xmesaContext; + + /* Find the XMesaBuffer which corresponds to the GLXDrawable 'draw' */ + if (ctx == MakeCurrent_PrevContext + && draw == MakeCurrent_PrevDrawable) { + drawBuffer = MakeCurrent_PrevDrawBuffer; + } + else { + drawBuffer = XMesaFindBuffer( dpy, draw ); + } + if (!drawBuffer) { + /* drawable must be a new window! */ + drawBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, draw ); + if (!drawBuffer) { + /* Out of memory, or context/drawable depth mismatch */ + return False; + } + } + + /* Find the XMesaBuffer which corresponds to the GLXDrawable 'read' */ + if (ctx == MakeCurrent_PrevContext + && read == MakeCurrent_PrevReadable) { + readBuffer = MakeCurrent_PrevReadBuffer; + } + else { + readBuffer = XMesaFindBuffer( dpy, read ); + } + if (!readBuffer) { + /* drawable must be a new window! */ + readBuffer = XMesaCreateWindowBuffer( xmctx->xm_visual, read ); + if (!readBuffer) { + /* Out of memory, or context/drawable depth mismatch */ + return False; + } + } + + if (no_rast && + MakeCurrent_PrevContext == ctx && + MakeCurrent_PrevDrawable == draw && + MakeCurrent_PrevReadable == read && + MakeCurrent_PrevDrawBuffer == drawBuffer && + MakeCurrent_PrevReadBuffer == readBuffer) + return True; + + MakeCurrent_PrevContext = ctx; + MakeCurrent_PrevDrawable = draw; + MakeCurrent_PrevReadable = read; + MakeCurrent_PrevDrawBuffer = drawBuffer; + MakeCurrent_PrevReadBuffer = readBuffer; + + /* Now make current! */ + if (XMesaMakeCurrent2(xmctx, drawBuffer, readBuffer)) { + ((__GLXcontext *) ctx)->currentDpy = dpy; + ((__GLXcontext *) ctx)->currentDrawable = draw; + ((__GLXcontext *) ctx)->currentReadable = read; + return True; + } + else { + return False; + } + } + else if (!ctx && !draw && !read) { + /* release current context w/out assigning new one. */ + XMesaMakeCurrent2( NULL, NULL, NULL ); + MakeCurrent_PrevContext = 0; + MakeCurrent_PrevDrawable = 0; + MakeCurrent_PrevReadable = 0; + MakeCurrent_PrevDrawBuffer = 0; + MakeCurrent_PrevReadBuffer = 0; + return True; + } + else { + /* The args must either all be non-zero or all zero. + * This is an error. + */ + return False; + } +} + + +static Bool +Fake_glXMakeCurrent( Display *dpy, GLXDrawable drawable, GLXContext ctx ) +{ + return Fake_glXMakeContextCurrent( dpy, drawable, drawable, ctx ); +} + + +static GLXPixmap +Fake_glXCreateGLXPixmap( Display *dpy, XVisualInfo *visinfo, Pixmap pixmap ) +{ + XMesaVisual v; + XMesaBuffer b; + + v = find_glx_visual( dpy, visinfo ); + if (!v) { + v = create_glx_visual( dpy, visinfo ); + if (!v) { + /* unusable visual */ + return 0; + } + } + + b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + if (!b) { + return 0; + } + return b->drawable; +} + + +/*** GLX_MESA_pixmap_colormap ***/ + +static GLXPixmap +Fake_glXCreateGLXPixmapMESA( Display *dpy, XVisualInfo *visinfo, + Pixmap pixmap, Colormap cmap ) +{ + XMesaVisual v; + XMesaBuffer b; + + v = find_glx_visual( dpy, visinfo ); + if (!v) { + v = create_glx_visual( dpy, visinfo ); + if (!v) { + /* unusable visual */ + return 0; + } + } + + b = XMesaCreatePixmapBuffer( v, pixmap, cmap ); + if (!b) { + return 0; + } + return b->drawable; +} + + +static void +Fake_glXDestroyGLXPixmap( Display *dpy, GLXPixmap pixmap ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, pixmap); + if (b) { + XMesaDestroyBuffer(b); + } + else if (_mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "Mesa: glXDestroyGLXPixmap: invalid pixmap\n"); + } +} + + +static void +Fake_glXCopyContext( Display *dpy, GLXContext src, GLXContext dst, + unsigned long mask ) +{ + struct fake_glx_context *fakeSrc = (struct fake_glx_context *) src; + struct fake_glx_context *fakeDst = (struct fake_glx_context *) dst; + XMesaContext xm_src = fakeSrc->xmesaContext; + XMesaContext xm_dst = fakeDst->xmesaContext; + (void) dpy; + if (MakeCurrent_PrevContext == src) { + _mesa_Flush(); + } + st_copy_context_state( xm_src->st, xm_dst->st, (GLuint) mask ); +} + + +static Bool +Fake_glXQueryExtension( Display *dpy, int *errorb, int *event ) +{ + /* Mesa's GLX isn't really an X extension but we try to act like one. */ + (void) dpy; + (void) errorb; + (void) event; + return True; +} + + +extern void _kw_ungrab_all( Display *dpy ); +void _kw_ungrab_all( Display *dpy ) +{ + XUngrabPointer( dpy, CurrentTime ); + XUngrabKeyboard( dpy, CurrentTime ); +} + + +static void +Fake_glXDestroyContext( Display *dpy, GLXContext ctx ) +{ + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + (void) dpy; + MakeCurrent_PrevContext = 0; + MakeCurrent_PrevDrawable = 0; + MakeCurrent_PrevReadable = 0; + MakeCurrent_PrevDrawBuffer = 0; + MakeCurrent_PrevReadBuffer = 0; + XMesaDestroyContext( glxCtx->xmesaContext ); + XMesaGarbageCollect(); + _mesa_free(glxCtx); +} + + +static Bool +Fake_glXIsDirect( Display *dpy, GLXContext ctx ) +{ + (void) dpy; + (void) ctx; + return False; +} + + + +static void +Fake_glXSwapBuffers( Display *dpy, GLXDrawable drawable ) +{ + XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); + static boolean firsttime = 1, no_rast = 0; + + if (firsttime) { + no_rast = getenv("SP_NO_RAST") != NULL; + firsttime = 0; + } + + if (no_rast) + return; + + if (buffer) { + XMesaSwapBuffers(buffer); + } + else if (_mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "glXSwapBuffers: invalid drawable 0x%x\n", + (int) drawable); + } +} + + + +/*** GLX_MESA_copy_sub_buffer ***/ + +static void +Fake_glXCopySubBufferMESA( Display *dpy, GLXDrawable drawable, + int x, int y, int width, int height ) +{ + XMesaBuffer buffer = XMesaFindBuffer( dpy, drawable ); + if (buffer) { + XMesaCopySubBuffer(buffer, x, y, width, height); + } + else if (_mesa_getenv("MESA_DEBUG")) { + _mesa_warning(NULL, "Mesa: glXCopySubBufferMESA: invalid drawable\n"); + } +} + + +static Bool +Fake_glXQueryVersion( Display *dpy, int *maj, int *min ) +{ + (void) dpy; + /* Return GLX version, not Mesa version */ + assert(CLIENT_MAJOR_VERSION == SERVER_MAJOR_VERSION); + *maj = CLIENT_MAJOR_VERSION; + *min = MIN2( CLIENT_MINOR_VERSION, SERVER_MINOR_VERSION ); + return True; +} + + +/* + * Query the GLX attributes of the given XVisualInfo. + */ +static int +get_config( XMesaVisual xmvis, int attrib, int *value, GLboolean fbconfig ) +{ + ASSERT(xmvis); + switch(attrib) { + case GLX_USE_GL: + if (fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = (int) True; + return 0; + case GLX_BUFFER_SIZE: + *value = xmvis->visinfo->depth; + return 0; + case GLX_LEVEL: + *value = xmvis->mesa_visual.level; + return 0; + case GLX_RGBA: + if (fbconfig) + return GLX_BAD_ATTRIBUTE; + if (xmvis->mesa_visual.rgbMode) { + *value = True; + } + else { + *value = False; + } + return 0; + case GLX_DOUBLEBUFFER: + *value = (int) xmvis->mesa_visual.doubleBufferMode; + return 0; + case GLX_STEREO: + *value = (int) xmvis->mesa_visual.stereoMode; + return 0; + case GLX_AUX_BUFFERS: + *value = xmvis->mesa_visual.numAuxBuffers; + return 0; + case GLX_RED_SIZE: + *value = xmvis->mesa_visual.redBits; + return 0; + case GLX_GREEN_SIZE: + *value = xmvis->mesa_visual.greenBits; + return 0; + case GLX_BLUE_SIZE: + *value = xmvis->mesa_visual.blueBits; + return 0; + case GLX_ALPHA_SIZE: + *value = xmvis->mesa_visual.alphaBits; + return 0; + case GLX_DEPTH_SIZE: + *value = xmvis->mesa_visual.depthBits; + return 0; + case GLX_STENCIL_SIZE: + *value = xmvis->mesa_visual.stencilBits; + return 0; + case GLX_ACCUM_RED_SIZE: + *value = xmvis->mesa_visual.accumRedBits; + return 0; + case GLX_ACCUM_GREEN_SIZE: + *value = xmvis->mesa_visual.accumGreenBits; + return 0; + case GLX_ACCUM_BLUE_SIZE: + *value = xmvis->mesa_visual.accumBlueBits; + return 0; + case GLX_ACCUM_ALPHA_SIZE: + *value = xmvis->mesa_visual.accumAlphaBits; + return 0; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_X_VISUAL_TYPE_EXT: + switch (xmvis->visinfo->CLASS) { + case StaticGray: *value = GLX_STATIC_GRAY_EXT; return 0; + case GrayScale: *value = GLX_GRAY_SCALE_EXT; return 0; + case StaticColor: *value = GLX_STATIC_GRAY_EXT; return 0; + case PseudoColor: *value = GLX_PSEUDO_COLOR_EXT; return 0; + case TrueColor: *value = GLX_TRUE_COLOR_EXT; return 0; + case DirectColor: *value = GLX_DIRECT_COLOR_EXT; return 0; + } + return 0; + case GLX_TRANSPARENT_TYPE_EXT: + /* normal planes */ + *value = GLX_NONE_EXT; + return 0; + case GLX_TRANSPARENT_INDEX_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_RED_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_GREEN_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_BLUE_VALUE_EXT: + /* undefined */ + return 0; + case GLX_TRANSPARENT_ALPHA_VALUE_EXT: + /* undefined */ + return 0; + + /* + * GLX_EXT_visual_info extension + */ + case GLX_VISUAL_CAVEAT_EXT: + /* test for zero, just in case */ + if (xmvis->mesa_visual.visualRating > 0) + *value = xmvis->mesa_visual.visualRating; + else + *value = GLX_NONE_EXT; + return 0; + + /* + * GLX_ARB_multisample + */ + case GLX_SAMPLE_BUFFERS_ARB: + *value = 0; + return 0; + case GLX_SAMPLES_ARB: + *value = 0; + return 0; + + /* + * For FBConfigs: + */ + case GLX_SCREEN_EXT: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = xmvis->visinfo->screen; + break; + case GLX_DRAWABLE_TYPE: /*SGIX too */ + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = GLX_WINDOW_BIT | GLX_PIXMAP_BIT | GLX_PBUFFER_BIT; + break; + case GLX_RENDER_TYPE_SGIX: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + if (xmvis->mesa_visual.rgbMode) + *value = GLX_RGBA_BIT; + else + *value = GLX_COLOR_INDEX_BIT; + break; + case GLX_X_RENDERABLE_SGIX: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = True; /* XXX really? */ + break; + case GLX_FBCONFIG_ID_SGIX: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = xmvis->visinfo->visualid; + break; + case GLX_MAX_PBUFFER_WIDTH: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + /* XXX or MAX_WIDTH? */ + *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen); + break; + case GLX_MAX_PBUFFER_HEIGHT: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = DisplayHeight(xmvis->display, xmvis->visinfo->screen); + break; + case GLX_MAX_PBUFFER_PIXELS: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = DisplayWidth(xmvis->display, xmvis->visinfo->screen) * + DisplayHeight(xmvis->display, xmvis->visinfo->screen); + break; + case GLX_VISUAL_ID: + if (!fbconfig) + return GLX_BAD_ATTRIBUTE; + *value = xmvis->visinfo->visualid; + break; + +#ifdef GLX_EXT_texture_from_pixmap + case GLX_BIND_TO_TEXTURE_RGB_EXT: + *value = True; /*XXX*/ + break; + case GLX_BIND_TO_TEXTURE_RGBA_EXT: + /* XXX review */ + *value = xmvis->mesa_visual.alphaBits > 0 ? True : False; + break; + case GLX_BIND_TO_MIPMAP_TEXTURE_EXT: + *value = True; /*XXX*/ + break; + case GLX_BIND_TO_TEXTURE_TARGETS_EXT: + *value = (GLX_TEXTURE_1D_BIT_EXT | + GLX_TEXTURE_2D_BIT_EXT | + GLX_TEXTURE_RECTANGLE_BIT_EXT); /*XXX*/ + break; + case GLX_Y_INVERTED_EXT: + *value = True; /*XXX*/ + break; +#endif + + default: + return GLX_BAD_ATTRIBUTE; + } + return Success; +} + + +static int +Fake_glXGetConfig( Display *dpy, XVisualInfo *visinfo, + int attrib, int *value ) +{ + XMesaVisual xmvis; + int k; + if (!dpy || !visinfo) + return GLX_BAD_ATTRIBUTE; + + xmvis = find_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* this visual wasn't obtained with glXChooseVisual */ + xmvis = create_glx_visual( dpy, visinfo ); + if (!xmvis) { + /* this visual can't be used for GL rendering */ + if (attrib==GLX_USE_GL) { + *value = (int) False; + return 0; + } + else { + return GLX_BAD_VISUAL; + } + } + } + + k = get_config(xmvis, attrib, value, GL_FALSE); + return k; +} + + +static void +Fake_glXWaitGL( void ) +{ + XMesaContext xmesa = XMesaGetCurrentContext(); + XMesaFlush( xmesa ); +} + + + +static void +Fake_glXWaitX( void ) +{ + XMesaContext xmesa = XMesaGetCurrentContext(); + XMesaFlush( xmesa ); +} + + +static const char * +get_extensions( void ) +{ + return EXTENSIONS; +} + + + +/* GLX 1.1 and later */ +static const char * +Fake_glXQueryExtensionsString( Display *dpy, int screen ) +{ + (void) dpy; + (void) screen; + return get_extensions(); +} + + + +/* GLX 1.1 and later */ +static const char * +Fake_glXQueryServerString( Display *dpy, int screen, int name ) +{ + static char version[1000]; + _mesa_sprintf(version, "%d.%d %s", + SERVER_MAJOR_VERSION, SERVER_MINOR_VERSION, MESA_GLX_VERSION); + + (void) dpy; + (void) screen; + + switch (name) { + case GLX_EXTENSIONS: + return get_extensions(); + case GLX_VENDOR: + return VENDOR; + case GLX_VERSION: + return version; + default: + return NULL; + } +} + + + +/* GLX 1.1 and later */ +static const char * +Fake_glXGetClientString( Display *dpy, int name ) +{ + static char version[1000]; + _mesa_sprintf(version, "%d.%d %s", CLIENT_MAJOR_VERSION, + CLIENT_MINOR_VERSION, MESA_GLX_VERSION); + + (void) dpy; + + switch (name) { + case GLX_EXTENSIONS: + return get_extensions(); + case GLX_VENDOR: + return VENDOR; + case GLX_VERSION: + return version; + default: + return NULL; + } +} + + + +/* + * GLX 1.3 and later + */ + + +static int +Fake_glXGetFBConfigAttrib( Display *dpy, GLXFBConfig config, + int attribute, int *value ) +{ + XMesaVisual v = (XMesaVisual) config; + (void) dpy; + (void) config; + + if (!dpy || !config || !value) + return -1; + + return get_config(v, attribute, value, GL_TRUE); +} + + +static GLXFBConfig * +Fake_glXGetFBConfigs( Display *dpy, int screen, int *nelements ) +{ + XVisualInfo *visuals, visTemplate; + const long visMask = VisualScreenMask; + int i; + + /* Get list of all X visuals */ + visTemplate.screen = screen; + visuals = XGetVisualInfo(dpy, visMask, &visTemplate, nelements); + if (*nelements > 0) { + XMesaVisual *results; + results = (XMesaVisual *) _mesa_malloc(*nelements * sizeof(XMesaVisual)); + if (!results) { + *nelements = 0; + return NULL; + } + for (i = 0; i < *nelements; i++) { + results[i] = create_glx_visual(dpy, visuals + i); + } + return (GLXFBConfig *) results; + } + return NULL; +} + + +static GLXFBConfig * +Fake_glXChooseFBConfig( Display *dpy, int screen, + const int *attribList, int *nitems ) +{ + XMesaVisual xmvis; + + if (!attribList || !attribList[0]) { + /* return list of all configs (per GLX_SGIX_fbconfig spec) */ + return Fake_glXGetFBConfigs(dpy, screen, nitems); + } + + xmvis = choose_visual(dpy, screen, attribList, GL_TRUE); + if (xmvis) { + GLXFBConfig *config = (GLXFBConfig *) _mesa_malloc(sizeof(XMesaVisual)); + if (!config) { + *nitems = 0; + return NULL; + } + *nitems = 1; + config[0] = (GLXFBConfig) xmvis; + return (GLXFBConfig *) config; + } + else { + *nitems = 0; + return NULL; + } +} + + +static XVisualInfo * +Fake_glXGetVisualFromFBConfig( Display *dpy, GLXFBConfig config ) +{ + if (dpy && config) { + XMesaVisual xmvis = (XMesaVisual) config; +#if 0 + return xmvis->vishandle; +#else + /* create a new vishandle - the cached one may be stale */ + xmvis->vishandle = (XVisualInfo *) _mesa_malloc(sizeof(XVisualInfo)); + if (xmvis->vishandle) { + _mesa_memcpy(xmvis->vishandle, xmvis->visinfo, sizeof(XVisualInfo)); + } + return xmvis->vishandle; +#endif + } + else { + return NULL; + } +} + + +static GLXWindow +Fake_glXCreateWindow( Display *dpy, GLXFBConfig config, Window win, + const int *attribList ) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + if (!xmvis) + return 0; + + xmbuf = XMesaCreateWindowBuffer(xmvis, win); + if (!xmbuf) + return 0; + + (void) dpy; + (void) attribList; /* Ignored in GLX 1.3 */ + + return win; /* A hack for now */ +} + + +static void +Fake_glXDestroyWindow( Display *dpy, GLXWindow window ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable) window); + if (b) + XMesaDestroyBuffer(b); + /* don't destroy X window */ +} + + +/* XXX untested */ +static GLXPixmap +Fake_glXCreatePixmap( Display *dpy, GLXFBConfig config, Pixmap pixmap, + const int *attribList ) +{ + XMesaVisual v = (XMesaVisual) config; + XMesaBuffer b; + const int *attr; + int target = 0, format = 0, mipmap = 0; + int value; + + if (!dpy || !config || !pixmap) + return 0; + + for (attr = attribList; *attr; attr++) { + switch (*attr) { + case GLX_TEXTURE_FORMAT_EXT: + attr++; + switch (*attr) { + case GLX_TEXTURE_FORMAT_NONE_EXT: + case GLX_TEXTURE_FORMAT_RGB_EXT: + case GLX_TEXTURE_FORMAT_RGBA_EXT: + format = *attr; + break; + default: + /* error */ + return 0; + } + break; + case GLX_TEXTURE_TARGET_EXT: + attr++; + switch (*attr) { + case GLX_TEXTURE_1D_EXT: + case GLX_TEXTURE_2D_EXT: + case GLX_TEXTURE_RECTANGLE_EXT: + target = *attr; + break; + default: + /* error */ + return 0; + } + break; + case GLX_MIPMAP_TEXTURE_EXT: + attr++; + if (*attr) + mipmap = 1; + break; + default: + /* error */ + return 0; + } + } + + if (format == GLX_TEXTURE_FORMAT_RGB_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_RGB_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + else if (format == GLX_TEXTURE_FORMAT_RGBA_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_RGBA_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + if (mipmap) { + if (get_config(v, GLX_BIND_TO_MIPMAP_TEXTURE_EXT, + &value, GL_TRUE) != Success + || !value) { + return 0; /* error! */ + } + } + if (target == GLX_TEXTURE_1D_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_1D_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + else if (target == GLX_TEXTURE_2D_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_2D_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + if (target == GLX_TEXTURE_RECTANGLE_EXT) { + if (get_config(v, GLX_BIND_TO_TEXTURE_TARGETS_EXT, + &value, GL_TRUE) != Success + || (value & GLX_TEXTURE_RECTANGLE_BIT_EXT) == 0) { + return 0; /* error! */ + } + } + + if (format || target || mipmap) { + /* texture from pixmap */ + b = XMesaCreatePixmapTextureBuffer(v, pixmap, 0, format, target, mipmap); + } + else { + b = XMesaCreatePixmapBuffer( v, pixmap, 0 ); + } + if (!b) { + return 0; + } + + return pixmap; +} + + +static void +Fake_glXDestroyPixmap( Display *dpy, GLXPixmap pixmap ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, (Drawable)pixmap); + if (b) + XMesaDestroyBuffer(b); + /* don't destroy X pixmap */ +} + + +static GLXPbuffer +Fake_glXCreatePbuffer( Display *dpy, GLXFBConfig config, + const int *attribList ) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + const int *attrib; + int width = 0, height = 0; + GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; + + (void) dpy; + + for (attrib = attribList; *attrib; attrib++) { + switch (*attrib) { + case GLX_PBUFFER_WIDTH: + attrib++; + width = *attrib; + break; + case GLX_PBUFFER_HEIGHT: + attrib++; + height = *attrib; + break; + case GLX_PRESERVED_CONTENTS: + attrib++; + preserveContents = *attrib; /* ignored */ + break; + case GLX_LARGEST_PBUFFER: + attrib++; + useLargest = *attrib; /* ignored */ + break; + default: + return 0; + } + } + + /* not used at this time */ + (void) useLargest; + (void) preserveContents; + + if (width == 0 || height == 0) + return 0; + + xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); + /* A GLXPbuffer handle must be an X Drawable because that's what + * glXMakeCurrent takes. + */ + if (xmbuf) + return (GLXPbuffer) xmbuf->drawable; + else + return 0; +} + + +static void +Fake_glXDestroyPbuffer( Display *dpy, GLXPbuffer pbuf ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, pbuf); + if (b) { + XMesaDestroyBuffer(b); + } +} + + +static void +Fake_glXQueryDrawable( Display *dpy, GLXDrawable draw, int attribute, + unsigned int *value ) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, draw); + if (!xmbuf) + return; + + switch (attribute) { + case GLX_WIDTH: + *value = xmesa_buffer_width(xmbuf); + break; + case GLX_HEIGHT: + *value = xmesa_buffer_width(xmbuf); + break; + case GLX_PRESERVED_CONTENTS: + *value = True; + break; + case GLX_LARGEST_PBUFFER: + *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf); + break; + case GLX_FBCONFIG_ID: + *value = xmbuf->xm_visual->visinfo->visualid; + return; +#ifdef GLX_EXT_texture_from_pixmap + case GLX_TEXTURE_FORMAT_EXT: + *value = xmbuf->TextureFormat; + break; + case GLX_TEXTURE_TARGET_EXT: + *value = xmbuf->TextureTarget; + break; + case GLX_MIPMAP_TEXTURE_EXT: + *value = xmbuf->TextureMipmap; + break; +#endif + + default: + return; /* raise BadValue error */ + } +} + + +static GLXContext +Fake_glXCreateNewContext( Display *dpy, GLXFBConfig config, + int renderType, GLXContext shareList, Bool direct ) +{ + struct fake_glx_context *glxCtx; + struct fake_glx_context *shareCtx = (struct fake_glx_context *) shareList; + XMesaVisual xmvis = (XMesaVisual) config; + + if (!dpy || !config || + (renderType != GLX_RGBA_TYPE && renderType != GLX_COLOR_INDEX_TYPE)) + return 0; + + glxCtx = CALLOC_STRUCT(fake_glx_context); + if (!glxCtx) + return 0; + + /* deallocate unused windows/buffers */ + XMesaGarbageCollect(); + + glxCtx->xmesaContext = XMesaCreateContext(xmvis, + shareCtx ? shareCtx->xmesaContext : NULL); + if (!glxCtx->xmesaContext) { + _mesa_free(glxCtx); + return NULL; + } + + glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.currentDpy = dpy; + glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ + + assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + + return (GLXContext) glxCtx; +} + + +static int +Fake_glXQueryContext( Display *dpy, GLXContext ctx, int attribute, int *value ) +{ + struct fake_glx_context *glxCtx = (struct fake_glx_context *) ctx; + XMesaContext xmctx = glxCtx->xmesaContext; + + (void) dpy; + (void) ctx; + + switch (attribute) { + case GLX_FBCONFIG_ID: + *value = xmctx->xm_visual->visinfo->visualid; + break; + case GLX_RENDER_TYPE: + if (xmctx->xm_visual->mesa_visual.rgbMode) + *value = GLX_RGBA_BIT; + else + *value = GLX_COLOR_INDEX_BIT; + break; + case GLX_SCREEN: + *value = 0; + return Success; + default: + return GLX_BAD_ATTRIBUTE; + } + return 0; +} + + +static void +Fake_glXSelectEvent( Display *dpy, GLXDrawable drawable, unsigned long mask ) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) + xmbuf->selectedEvents = mask; +} + + +static void +Fake_glXGetSelectedEvent( Display *dpy, GLXDrawable drawable, + unsigned long *mask ) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) + *mask = xmbuf->selectedEvents; + else + *mask = 0; +} + + + +/*** GLX_SGI_swap_control ***/ + +static int +Fake_glXSwapIntervalSGI(int interval) +{ + (void) interval; + return 0; +} + + + +/*** GLX_SGI_video_sync ***/ + +static unsigned int FrameCounter = 0; + +static int +Fake_glXGetVideoSyncSGI(unsigned int *count) +{ + /* this is a bogus implementation */ + *count = FrameCounter++; + return 0; +} + +static int +Fake_glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +{ + if (divisor <= 0 || remainder < 0) + return GLX_BAD_VALUE; + /* this is a bogus implementation */ + FrameCounter++; + while (FrameCounter % divisor != remainder) + FrameCounter++; + *count = FrameCounter; + return 0; +} + + + +/*** GLX_SGI_make_current_read ***/ + +static Bool +Fake_glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + return Fake_glXMakeContextCurrent( dpy, draw, read, ctx ); +} + +/* not used +static GLXDrawable +Fake_glXGetCurrentReadDrawableSGI(void) +{ + return 0; +} +*/ + + +/*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + +static GLXVideoSourceSGIX +Fake_glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) +{ + (void) dpy; + (void) screen; + (void) server; + (void) path; + (void) nodeClass; + (void) drainNode; + return 0; +} + +static void +Fake_glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) +{ + (void) dpy; + (void) src; +} + +#endif + + +/*** GLX_EXT_import_context ***/ + +static void +Fake_glXFreeContextEXT(Display *dpy, GLXContext context) +{ + (void) dpy; + (void) context; +} + +static GLXContextID +Fake_glXGetContextIDEXT(const GLXContext context) +{ + (void) context; + return 0; +} + +static GLXContext +Fake_glXImportContextEXT(Display *dpy, GLXContextID contextID) +{ + (void) dpy; + (void) contextID; + return 0; +} + +static int +Fake_glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute, int *value) +{ + (void) dpy; + (void) context; + (void) attribute; + (void) value; + return 0; +} + + + +/*** GLX_SGIX_fbconfig ***/ + +static int +Fake_glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) +{ + return Fake_glXGetFBConfigAttrib(dpy, config, attribute, value); +} + +static GLXFBConfigSGIX * +Fake_glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) +{ + return (GLXFBConfig *) Fake_glXChooseFBConfig(dpy, screen, attrib_list, nelements); +} + + +static GLXPixmap +Fake_glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf = XMesaCreatePixmapBuffer(xmvis, pixmap, 0); + return xmbuf->drawable; /* need to return an X ID */ +} + + +static GLXContext +Fake_glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) +{ + XMesaVisual xmvis = (XMesaVisual) config; + struct fake_glx_context *glxCtx; + struct fake_glx_context *shareCtx = (struct fake_glx_context *) share_list; + + glxCtx = CALLOC_STRUCT(fake_glx_context); + if (!glxCtx) + return 0; + + /* deallocate unused windows/buffers */ + XMesaGarbageCollect(); + + glxCtx->xmesaContext = XMesaCreateContext(xmvis, + shareCtx ? shareCtx->xmesaContext : NULL); + if (!glxCtx->xmesaContext) { + _mesa_free(glxCtx); + return NULL; + } + + glxCtx->glxContext.isDirect = GL_FALSE; + glxCtx->glxContext.currentDpy = dpy; + glxCtx->glxContext.xid = (XID) glxCtx; /* self pointer */ + + assert((void *) glxCtx == (void *) &(glxCtx->glxContext)); + + return (GLXContext) glxCtx; +} + + +static XVisualInfo * +Fake_glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) +{ + return Fake_glXGetVisualFromFBConfig(dpy, config); +} + + +static GLXFBConfigSGIX +Fake_glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) +{ + XMesaVisual xmvis = find_glx_visual(dpy, vis); + if (!xmvis) { + /* This visual wasn't found with glXChooseVisual() */ + xmvis = create_glx_visual(dpy, vis); + } + + return (GLXFBConfigSGIX) xmvis; +} + + + +/*** GLX_SGIX_pbuffer ***/ + +static GLXPbufferSGIX +Fake_glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, + unsigned int width, unsigned int height, + int *attribList) +{ + XMesaVisual xmvis = (XMesaVisual) config; + XMesaBuffer xmbuf; + const int *attrib; + GLboolean useLargest = GL_FALSE, preserveContents = GL_FALSE; + + (void) dpy; + + for (attrib = attribList; attrib && *attrib; attrib++) { + switch (*attrib) { + case GLX_PRESERVED_CONTENTS_SGIX: + attrib++; + preserveContents = *attrib; /* ignored */ + break; + case GLX_LARGEST_PBUFFER_SGIX: + attrib++; + useLargest = *attrib; /* ignored */ + break; + default: + return 0; + } + } + + /* not used at this time */ + (void) useLargest; + (void) preserveContents; + + xmbuf = XMesaCreatePBuffer( xmvis, 0, width, height); + /* A GLXPbuffer handle must be an X Drawable because that's what + * glXMakeCurrent takes. + */ + return (GLXPbuffer) xmbuf->drawable; +} + + +static void +Fake_glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); + if (xmbuf) { + XMesaDestroyBuffer(xmbuf); + } +} + + +static int +Fake_glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value) +{ + const XMesaBuffer xmbuf = XMesaFindBuffer(dpy, pbuf); + + if (!xmbuf) { + /* Generate GLXBadPbufferSGIX for bad pbuffer */ + return 0; + } + + switch (attribute) { + case GLX_PRESERVED_CONTENTS_SGIX: + *value = True; + break; + case GLX_LARGEST_PBUFFER_SGIX: + *value = xmesa_buffer_width(xmbuf) * xmesa_buffer_height(xmbuf); + break; + case GLX_WIDTH_SGIX: + *value = xmesa_buffer_width(xmbuf); + break; + case GLX_HEIGHT_SGIX: + *value = xmesa_buffer_height(xmbuf); + break; + case GLX_EVENT_MASK_SGIX: + *value = 0; /* XXX might be wrong */ + break; + default: + *value = 0; + } + return 0; +} + + +static void +Fake_glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) { + /* Note: we'll never generate clobber events */ + xmbuf->selectedEvents = mask; + } +} + + +static void +Fake_glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask) +{ + XMesaBuffer xmbuf = XMesaFindBuffer(dpy, drawable); + if (xmbuf) { + *mask = xmbuf->selectedEvents; + } + else { + *mask = 0; + } +} + + + +/*** GLX_SGI_cushion ***/ + +static void +Fake_glXCushionSGI(Display *dpy, Window win, float cushion) +{ + (void) dpy; + (void) win; + (void) cushion; +} + + + +/*** GLX_SGIX_video_resize ***/ + +static int +Fake_glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) window; + return 0; +} + +static int +Fake_glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) x; + (void) y; + (void) w; + (void) h; + return 0; +} + +static int +Fake_glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) x; + (void) y; + (void) w; + (void) h; + return 0; +} + +static int +Fake_glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) dx; + (void) dy; + (void) dw; + (void) dh; + return 0; +} + +static int +Fake_glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) +{ + (void) dpy; + (void) screen; + (void) channel; + (void) synctype; + return 0; +} + + + +/*** GLX_SGIX_dmbuffer **/ + +#if defined(_DM_BUFFER_H_) +static Bool +Fake_glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) +{ + (void) dpy; + (void) pbuffer; + (void) params; + (void) dmbuffer; + return False; +} +#endif + + +/*** GLX_SGIX_swap_group ***/ + +static void +Fake_glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) +{ + (void) dpy; + (void) drawable; + (void) member; +} + + + +/*** GLX_SGIX_swap_barrier ***/ + +static void +Fake_glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) +{ + (void) dpy; + (void) drawable; + (void) barrier; +} + +static Bool +Fake_glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) +{ + (void) dpy; + (void) screen; + (void) max; + return False; +} + + + +/*** GLX_SUN_get_transparent_index ***/ + +static Status +Fake_glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) +{ + (void) dpy; + (void) overlay; + (void) underlay; + (void) pTransparent; + return 0; +} + + + +/*** GLX_MESA_release_buffers ***/ + +/* + * Release the depth, stencil, accum buffers attached to a GLXDrawable + * (a window or pixmap) prior to destroying the GLXDrawable. + */ +static Bool +Fake_glXReleaseBuffersMESA( Display *dpy, GLXDrawable d ) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, d); + if (b) { + XMesaDestroyBuffer(b); + return True; + } + return False; +} + +/*** GLX_EXT_texture_from_pixmap ***/ + +static void +Fake_glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, + const int *attrib_list) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, drawable); + if (b) + XMesaBindTexImage(dpy, b, buffer, attrib_list); +} + +static void +Fake_glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) +{ + XMesaBuffer b = XMesaFindBuffer(dpy, drawable); + if (b) + XMesaReleaseTexImage(dpy, b, buffer); +} + + + +/** + * Create a new GLX API dispatch table with its function pointers + * initialized to point to Mesa's "fake" GLX API functions. + * + * Note: there used to be a similar function + * (_real_GetGLXDispatchTable) that returns a new dispatch table with + * all pointers initalized to point to "real" GLX functions (which + * understand GLX wire protocol, etc). + */ +struct _glxapi_table * +_mesa_GetGLXDispatchTable(void) +{ + static struct _glxapi_table glx; + + /* be sure our dispatch table size <= libGL's table */ + { + GLuint size = sizeof(struct _glxapi_table) / sizeof(void *); + (void) size; + assert(_glxapi_get_dispatch_table_size() >= size); + } + + /* initialize the whole table to no-ops */ + _glxapi_set_no_op_table(&glx); + + /* now initialize the table with the functions I implement */ + glx.ChooseVisual = Fake_glXChooseVisual; + glx.CopyContext = Fake_glXCopyContext; + glx.CreateContext = Fake_glXCreateContext; + glx.CreateGLXPixmap = Fake_glXCreateGLXPixmap; + glx.DestroyContext = Fake_glXDestroyContext; + glx.DestroyGLXPixmap = Fake_glXDestroyGLXPixmap; + glx.GetConfig = Fake_glXGetConfig; + /*glx.GetCurrentContext = Fake_glXGetCurrentContext;*/ + /*glx.GetCurrentDrawable = Fake_glXGetCurrentDrawable;*/ + glx.IsDirect = Fake_glXIsDirect; + glx.MakeCurrent = Fake_glXMakeCurrent; + glx.QueryExtension = Fake_glXQueryExtension; + glx.QueryVersion = Fake_glXQueryVersion; + glx.SwapBuffers = Fake_glXSwapBuffers; + glx.UseXFont = Fake_glXUseXFont; + glx.WaitGL = Fake_glXWaitGL; + glx.WaitX = Fake_glXWaitX; + + /*** GLX_VERSION_1_1 ***/ + glx.GetClientString = Fake_glXGetClientString; + glx.QueryExtensionsString = Fake_glXQueryExtensionsString; + glx.QueryServerString = Fake_glXQueryServerString; + + /*** GLX_VERSION_1_2 ***/ + /*glx.GetCurrentDisplay = Fake_glXGetCurrentDisplay;*/ + + /*** GLX_VERSION_1_3 ***/ + glx.ChooseFBConfig = Fake_glXChooseFBConfig; + glx.CreateNewContext = Fake_glXCreateNewContext; + glx.CreatePbuffer = Fake_glXCreatePbuffer; + glx.CreatePixmap = Fake_glXCreatePixmap; + glx.CreateWindow = Fake_glXCreateWindow; + glx.DestroyPbuffer = Fake_glXDestroyPbuffer; + glx.DestroyPixmap = Fake_glXDestroyPixmap; + glx.DestroyWindow = Fake_glXDestroyWindow; + /*glx.GetCurrentReadDrawable = Fake_glXGetCurrentReadDrawable;*/ + glx.GetFBConfigAttrib = Fake_glXGetFBConfigAttrib; + glx.GetFBConfigs = Fake_glXGetFBConfigs; + glx.GetSelectedEvent = Fake_glXGetSelectedEvent; + glx.GetVisualFromFBConfig = Fake_glXGetVisualFromFBConfig; + glx.MakeContextCurrent = Fake_glXMakeContextCurrent; + glx.QueryContext = Fake_glXQueryContext; + glx.QueryDrawable = Fake_glXQueryDrawable; + glx.SelectEvent = Fake_glXSelectEvent; + + /*** GLX_SGI_swap_control ***/ + glx.SwapIntervalSGI = Fake_glXSwapIntervalSGI; + + /*** GLX_SGI_video_sync ***/ + glx.GetVideoSyncSGI = Fake_glXGetVideoSyncSGI; + glx.WaitVideoSyncSGI = Fake_glXWaitVideoSyncSGI; + + /*** GLX_SGI_make_current_read ***/ + glx.MakeCurrentReadSGI = Fake_glXMakeCurrentReadSGI; + /*glx.GetCurrentReadDrawableSGI = Fake_glXGetCurrentReadDrawableSGI;*/ + +/*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + glx.CreateGLXVideoSourceSGIX = Fake_glXCreateGLXVideoSourceSGIX; + glx.DestroyGLXVideoSourceSGIX = Fake_glXDestroyGLXVideoSourceSGIX; +#endif + + /*** GLX_EXT_import_context ***/ + glx.FreeContextEXT = Fake_glXFreeContextEXT; + glx.GetContextIDEXT = Fake_glXGetContextIDEXT; + /*glx.GetCurrentDisplayEXT = Fake_glXGetCurrentDisplayEXT;*/ + glx.ImportContextEXT = Fake_glXImportContextEXT; + glx.QueryContextInfoEXT = Fake_glXQueryContextInfoEXT; + + /*** GLX_SGIX_fbconfig ***/ + glx.GetFBConfigAttribSGIX = Fake_glXGetFBConfigAttribSGIX; + glx.ChooseFBConfigSGIX = Fake_glXChooseFBConfigSGIX; + glx.CreateGLXPixmapWithConfigSGIX = Fake_glXCreateGLXPixmapWithConfigSGIX; + glx.CreateContextWithConfigSGIX = Fake_glXCreateContextWithConfigSGIX; + glx.GetVisualFromFBConfigSGIX = Fake_glXGetVisualFromFBConfigSGIX; + glx.GetFBConfigFromVisualSGIX = Fake_glXGetFBConfigFromVisualSGIX; + + /*** GLX_SGIX_pbuffer ***/ + glx.CreateGLXPbufferSGIX = Fake_glXCreateGLXPbufferSGIX; + glx.DestroyGLXPbufferSGIX = Fake_glXDestroyGLXPbufferSGIX; + glx.QueryGLXPbufferSGIX = Fake_glXQueryGLXPbufferSGIX; + glx.SelectEventSGIX = Fake_glXSelectEventSGIX; + glx.GetSelectedEventSGIX = Fake_glXGetSelectedEventSGIX; + + /*** GLX_SGI_cushion ***/ + glx.CushionSGI = Fake_glXCushionSGI; + + /*** GLX_SGIX_video_resize ***/ + glx.BindChannelToWindowSGIX = Fake_glXBindChannelToWindowSGIX; + glx.ChannelRectSGIX = Fake_glXChannelRectSGIX; + glx.QueryChannelRectSGIX = Fake_glXQueryChannelRectSGIX; + glx.QueryChannelDeltasSGIX = Fake_glXQueryChannelDeltasSGIX; + glx.ChannelRectSyncSGIX = Fake_glXChannelRectSyncSGIX; + + /*** GLX_SGIX_dmbuffer **/ +#if defined(_DM_BUFFER_H_) + glx.AssociateDMPbufferSGIX = NULL; +#endif + + /*** GLX_SGIX_swap_group ***/ + glx.JoinSwapGroupSGIX = Fake_glXJoinSwapGroupSGIX; + + /*** GLX_SGIX_swap_barrier ***/ + glx.BindSwapBarrierSGIX = Fake_glXBindSwapBarrierSGIX; + glx.QueryMaxSwapBarriersSGIX = Fake_glXQueryMaxSwapBarriersSGIX; + + /*** GLX_SUN_get_transparent_index ***/ + glx.GetTransparentIndexSUN = Fake_glXGetTransparentIndexSUN; + + /*** GLX_MESA_copy_sub_buffer ***/ + glx.CopySubBufferMESA = Fake_glXCopySubBufferMESA; + + /*** GLX_MESA_release_buffers ***/ + glx.ReleaseBuffersMESA = Fake_glXReleaseBuffersMESA; + + /*** GLX_MESA_pixmap_colormap ***/ + glx.CreateGLXPixmapMESA = Fake_glXCreateGLXPixmapMESA; + + /*** GLX_EXT_texture_from_pixmap ***/ + glx.BindTexImageEXT = Fake_glXBindTexImageEXT; + glx.ReleaseTexImageEXT = Fake_glXReleaseTexImageEXT; + + return &glx; +} diff --git a/src/gallium/state_trackers/glx/xlib/fakeglx.h b/src/gallium/state_trackers/glx/xlib/fakeglx.h new file mode 100644 index 00000000000..e5fd960072e --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/fakeglx.h @@ -0,0 +1,41 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef FAKEGLX_H +#define FAKEGLX_H + + +#include <X11/Xlib.h> + +struct _glxapi_table; + +extern struct _glxapi_table *_mesa_GetGLXDispatchTable(void); + +extern void Fake_glXUseXFont( Font font, int first, int count, int listbase ); + + +#endif + diff --git a/src/gallium/state_trackers/glx/xlib/fakeglx_fonts.c b/src/gallium/state_trackers/glx/xlib/fakeglx_fonts.c new file mode 100644 index 00000000000..e3590467563 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/fakeglx_fonts.c @@ -0,0 +1,373 @@ + +/* + * Mesa 3-D graphics library + * Version: 3.5 + * + * Copyright (C) 1999-2000 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* xfonts.c -- glXUseXFont() for Mesa written by + * Copyright (C) 1995 Thorsten.Ohl @ Physik.TH-Darmstadt.de + */ + +#include "context.h" +#include "imports.h" +#include "fakeglx.h" +#include <GL/glx.h> + + +/* Some debugging info. */ + +#ifdef DEBUG +#undef _R +#undef _G +#undef _B +#include <ctype.h> + +int debug_xfonts = 0; + +static void +dump_char_struct(XCharStruct * ch, char *prefix) +{ + printf("%slbearing = %d, rbearing = %d, width = %d\n", + prefix, ch->lbearing, ch->rbearing, ch->width); + printf("%sascent = %d, descent = %d, attributes = %u\n", + prefix, ch->ascent, ch->descent, (unsigned int) ch->attributes); +} + +static void +dump_font_struct(XFontStruct * font) +{ + printf("ascent = %d, descent = %d\n", font->ascent, font->descent); + printf("char_or_byte2 = (%u,%u)\n", + font->min_char_or_byte2, font->max_char_or_byte2); + printf("byte1 = (%u,%u)\n", font->min_byte1, font->max_byte1); + printf("all_chars_exist = %s\n", font->all_chars_exist ? "True" : "False"); + printf("default_char = %c (\\%03o)\n", + (char) (isprint(font->default_char) ? font->default_char : ' '), + font->default_char); + dump_char_struct(&font->min_bounds, "min> "); + dump_char_struct(&font->max_bounds, "max> "); +#if 0 + for (c = font->min_char_or_byte2; c <= font->max_char_or_byte2; c++) { + char prefix[8]; + sprintf(prefix, "%d> ", c); + dump_char_struct(&font->per_char[c], prefix); + } +#endif +} + +static void +dump_bitmap(unsigned int width, unsigned int height, GLubyte * bitmap) +{ + unsigned int x, y; + + printf(" "); + for (x = 0; x < 8 * width; x++) + printf("%o", 7 - (x % 8)); + putchar('\n'); + for (y = 0; y < height; y++) { + printf("%3o:", y); + for (x = 0; x < 8 * width; x++) + putchar((bitmap[width * (height - y - 1) + x / 8] & (1 << (7 - (x % + 8)))) + ? '*' : '.'); + printf(" "); + for (x = 0; x < width; x++) + printf("0x%02x, ", bitmap[width * (height - y - 1) + x]); + putchar('\n'); + } +} +#endif /* DEBUG */ + + +/* Implementation. */ + +/* Fill a BITMAP with a character C from thew current font + in the graphics context GC. WIDTH is the width in bytes + and HEIGHT is the height in bits. + + Note that the generated bitmaps must be used with + + glPixelStorei (GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei (GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei (GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei (GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei (GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei (GL_UNPACK_ALIGNMENT, 1); + + Possible optimizations: + + * use only one reusable pixmap with the maximum dimensions. + * draw the entire font into a single pixmap (careful with + proportional fonts!). +*/ + + +/* + * Generate OpenGL-compatible bitmap. + */ +static void +fill_bitmap(Display * dpy, Window win, GC gc, + unsigned int width, unsigned int height, + int x0, int y0, unsigned int c, GLubyte * bitmap) +{ + XImage *image; + unsigned int x, y; + Pixmap pixmap; + XChar2b char2b; + + pixmap = XCreatePixmap(dpy, win, 8 * width, height, 1); + XSetForeground(dpy, gc, 0); + XFillRectangle(dpy, pixmap, gc, 0, 0, 8 * width, height); + XSetForeground(dpy, gc, 1); + + char2b.byte1 = (c >> 8) & 0xff; + char2b.byte2 = (c & 0xff); + + XDrawString16(dpy, pixmap, gc, x0, y0, &char2b, 1); + + image = XGetImage(dpy, pixmap, 0, 0, 8 * width, height, 1, XYPixmap); + if (image) { + /* Fill the bitmap (X11 and OpenGL are upside down wrt each other). */ + for (y = 0; y < height; y++) + for (x = 0; x < 8 * width; x++) + if (XGetPixel(image, x, y)) + bitmap[width * (height - y - 1) + x / 8] |= + (1 << (7 - (x % 8))); + XDestroyImage(image); + } + + XFreePixmap(dpy, pixmap); +} + +/* + * determine if a given glyph is valid and return the + * corresponding XCharStruct. + */ +static XCharStruct * +isvalid(XFontStruct * fs, unsigned int which) +{ + unsigned int rows, pages; + unsigned int byte1 = 0, byte2 = 0; + int i, valid = 1; + + rows = fs->max_byte1 - fs->min_byte1 + 1; + pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; + + if (rows == 1) { + /* "linear" fonts */ + if ((fs->min_char_or_byte2 > which) || (fs->max_char_or_byte2 < which)) + valid = 0; + } + else { + /* "matrix" fonts */ + byte2 = which & 0xff; + byte1 = which >> 8; + if ((fs->min_char_or_byte2 > byte2) || + (fs->max_char_or_byte2 < byte2) || + (fs->min_byte1 > byte1) || (fs->max_byte1 < byte1)) + valid = 0; + } + + if (valid) { + if (fs->per_char) { + if (rows == 1) { + /* "linear" fonts */ + return (fs->per_char + (which - fs->min_char_or_byte2)); + } + else { + /* "matrix" fonts */ + i = ((byte1 - fs->min_byte1) * pages) + + (byte2 - fs->min_char_or_byte2); + return (fs->per_char + i); + } + } + else { + return (&fs->min_bounds); + } + } + return (NULL); +} + + +void +Fake_glXUseXFont(Font font, int first, int count, int listbase) +{ + Display *dpy; + Window win; + Pixmap pixmap; + GC gc; + XGCValues values; + unsigned long valuemask; + XFontStruct *fs; + GLint swapbytes, lsbfirst, rowlength; + GLint skiprows, skippixels, alignment; + unsigned int max_width, max_height, max_bm_width, max_bm_height; + GLubyte *bm; + int i; + + dpy = glXGetCurrentDisplay(); + if (!dpy) + return; /* I guess glXMakeCurrent wasn't called */ + win = RootWindow(dpy, DefaultScreen(dpy)); + + fs = XQueryFont(dpy, font); + if (!fs) { + _mesa_error(NULL, GL_INVALID_VALUE, + "Couldn't get font structure information"); + return; + } + + /* Allocate a bitmap that can fit all characters. */ + max_width = fs->max_bounds.rbearing - fs->min_bounds.lbearing; + max_height = fs->max_bounds.ascent + fs->max_bounds.descent; + max_bm_width = (max_width + 7) / 8; + max_bm_height = max_height; + + bm = (GLubyte *) MALLOC((max_bm_width * max_bm_height) * sizeof(GLubyte)); + if (!bm) { + XFreeFontInfo(NULL, fs, 1); + _mesa_error(NULL, GL_OUT_OF_MEMORY, + "Couldn't allocate bitmap in glXUseXFont()"); + return; + } + +#if 0 + /* get the page info */ + pages = fs->max_char_or_byte2 - fs->min_char_or_byte2 + 1; + firstchar = (fs->min_byte1 << 8) + fs->min_char_or_byte2; + lastchar = (fs->max_byte1 << 8) + fs->max_char_or_byte2; + rows = fs->max_byte1 - fs->min_byte1 + 1; + unsigned int first_char, last_char, pages, rows; +#endif + + /* Save the current packing mode for bitmaps. */ + glGetIntegerv(GL_UNPACK_SWAP_BYTES, &swapbytes); + glGetIntegerv(GL_UNPACK_LSB_FIRST, &lsbfirst); + glGetIntegerv(GL_UNPACK_ROW_LENGTH, &rowlength); + glGetIntegerv(GL_UNPACK_SKIP_ROWS, &skiprows); + glGetIntegerv(GL_UNPACK_SKIP_PIXELS, &skippixels); + glGetIntegerv(GL_UNPACK_ALIGNMENT, &alignment); + + /* Enforce a standard packing mode which is compatible with + fill_bitmap() from above. This is actually the default mode, + except for the (non)alignment. */ + glPixelStorei(GL_UNPACK_SWAP_BYTES, GL_FALSE); + glPixelStorei(GL_UNPACK_LSB_FIRST, GL_FALSE); + glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); + glPixelStorei(GL_UNPACK_SKIP_ROWS, 0); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, 0); + glPixelStorei(GL_UNPACK_ALIGNMENT, 1); + + pixmap = XCreatePixmap(dpy, win, 10, 10, 1); + values.foreground = BlackPixel(dpy, DefaultScreen(dpy)); + values.background = WhitePixel(dpy, DefaultScreen(dpy)); + values.font = fs->fid; + valuemask = GCForeground | GCBackground | GCFont; + gc = XCreateGC(dpy, pixmap, valuemask, &values); + XFreePixmap(dpy, pixmap); + +#ifdef DEBUG + if (debug_xfonts) + dump_font_struct(fs); +#endif + + for (i = 0; i < count; i++) { + unsigned int width, height, bm_width, bm_height; + GLfloat x0, y0, dx, dy; + XCharStruct *ch; + int x, y; + unsigned int c = first + i; + int list = listbase + i; + int valid; + + /* check on index validity and get the bounds */ + ch = isvalid(fs, c); + if (!ch) { + ch = &fs->max_bounds; + valid = 0; + } + else { + valid = 1; + } + +#ifdef DEBUG + if (debug_xfonts) { + char s[7]; + sprintf(s, isprint(c) ? "%c> " : "\\%03o> ", c); + dump_char_struct(ch, s); + } +#endif + + /* glBitmap()' parameters: + straight from the glXUseXFont(3) manpage. */ + width = ch->rbearing - ch->lbearing; + height = ch->ascent + ch->descent; + x0 = -ch->lbearing; + y0 = ch->descent - 0; /* XXX used to subtract 1 here */ + /* but that caused a conformace failure */ + dx = ch->width; + dy = 0; + + /* X11's starting point. */ + x = -ch->lbearing; + y = ch->ascent; + + /* Round the width to a multiple of eight. We will use this also + for the pixmap for capturing the X11 font. This is slightly + inefficient, but it makes the OpenGL part real easy. */ + bm_width = (width + 7) / 8; + bm_height = height; + + glNewList(list, GL_COMPILE); + if (valid && (bm_width > 0) && (bm_height > 0)) { + + MEMSET(bm, '\0', bm_width * bm_height); + fill_bitmap(dpy, win, gc, bm_width, bm_height, x, y, c, bm); + + glBitmap(width, height, x0, y0, dx, dy, bm); +#ifdef DEBUG + if (debug_xfonts) { + printf("width/height = %u/%u\n", width, height); + printf("bm_width/bm_height = %u/%u\n", bm_width, bm_height); + dump_bitmap(bm_width, bm_height, bm); + } +#endif + } + else { + glBitmap(0, 0, 0.0, 0.0, dx, dy, NULL); + } + glEndList(); + } + + FREE(bm); + XFreeFontInfo(NULL, fs, 1); + XFreeGC(dpy, gc); + + /* Restore saved packing modes. */ + glPixelStorei(GL_UNPACK_SWAP_BYTES, swapbytes); + glPixelStorei(GL_UNPACK_LSB_FIRST, lsbfirst); + glPixelStorei(GL_UNPACK_ROW_LENGTH, rowlength); + glPixelStorei(GL_UNPACK_SKIP_ROWS, skiprows); + glPixelStorei(GL_UNPACK_SKIP_PIXELS, skippixels); + glPixelStorei(GL_UNPACK_ALIGNMENT, alignment); +} diff --git a/src/gallium/state_trackers/glx/xlib/glxapi.c b/src/gallium/state_trackers/glx/xlib/glxapi.c new file mode 100644 index 00000000000..1ff04804f15 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/glxapi.c @@ -0,0 +1,1246 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +/* + * This is the GLX API dispatcher. Calls to the glX* functions are + * either routed to the real GLX encoders or to Mesa's pseudo-GLX functions. + * See the glxapi.h file for more details. + */ + + +#include <assert.h> +#include <stdlib.h> +#include <stdio.h> +#include <string.h> +#include "main/glheader.h" +#include "glapi/glapi.h" +#include "glxapi.h" +#include "fakeglx.h" +#include "pipe/p_thread.h" + + +struct display_dispatch { + Display *Dpy; + struct _glxapi_table *Table; + struct display_dispatch *Next; +}; + +static struct display_dispatch *DispatchList = NULL; + + +/* Display -> Dispatch caching */ +static Display *prevDisplay = NULL; +static struct _glxapi_table *prevTable = NULL; + + +static struct _glxapi_table * +get_dispatch(Display *dpy) +{ + if (!dpy) + return NULL; + + /* search list of display/dispatch pairs for this display */ + { + const struct display_dispatch *d = DispatchList; + while (d) { + if (d->Dpy == dpy) { + prevDisplay = dpy; + prevTable = d->Table; + return d->Table; /* done! */ + } + d = d->Next; + } + } + + /* A new display, determine if we should use real GLX + * or Mesa's pseudo-GLX. + */ + { + struct _glxapi_table *t = _mesa_GetGLXDispatchTable(); + + if (t) { + struct display_dispatch *d; + d = (struct display_dispatch *) malloc(sizeof(struct display_dispatch)); + if (d) { + d->Dpy = dpy; + d->Table = t; + /* insert at head of list */ + d->Next = DispatchList; + DispatchList = d; + /* update cache */ + prevDisplay = dpy; + prevTable = t; + return t; + } + } + } + + /* If we get here that means we can't use real GLX on this display + * and the Mesa pseudo-GLX software renderer wasn't compiled in. + * Or, we ran out of memory! + */ + return NULL; +} + + +/* Don't use the GET_DISPATCH defined in glthread.h */ +#undef GET_DISPATCH + +#define GET_DISPATCH(DPY, TABLE) \ + if (DPY == prevDisplay) { \ + TABLE = prevTable; \ + } \ + else if (!DPY) { \ + TABLE = NULL; \ + } \ + else { \ + TABLE = get_dispatch(DPY); \ + } + + + + +/** + * GLX API current context. + */ +pipe_tsd ContextTSD; + + +static void +SetCurrentContext(GLXContext c) +{ + pipe_tsd_set(&ContextTSD, c); +} + + +/* + * GLX API entrypoints + */ + +/*** GLX_VERSION_1_0 ***/ + +XVisualInfo PUBLIC * +glXChooseVisual(Display *dpy, int screen, int *list) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->ChooseVisual)(dpy, screen, list); +} + + +void PUBLIC +glXCopyContext(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->CopyContext)(dpy, src, dst, mask); +} + + +GLXContext PUBLIC +glXCreateContext(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateContext)(dpy, visinfo, shareList, direct); +} + + +GLXPixmap PUBLIC +glXCreateGLXPixmap(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXPixmap)(dpy, visinfo, pixmap); +} + + +void PUBLIC +glXDestroyContext(Display *dpy, GLXContext ctx) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + if (glXGetCurrentContext() == ctx) + SetCurrentContext(NULL); + (t->DestroyContext)(dpy, ctx); +} + + +void PUBLIC +glXDestroyGLXPixmap(Display *dpy, GLXPixmap pixmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyGLXPixmap)(dpy, pixmap); +} + + +int PUBLIC +glXGetConfig(Display *dpy, XVisualInfo *visinfo, int attrib, int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return GLX_NO_EXTENSION; + return (t->GetConfig)(dpy, visinfo, attrib, value); +} + + +GLXContext PUBLIC +glXGetCurrentContext(void) +{ + return (GLXContext) pipe_tsd_get(&ContextTSD); +} + + +GLXDrawable PUBLIC +glXGetCurrentDrawable(void) +{ + __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); + return gc ? gc->currentDrawable : 0; +} + + +Bool PUBLIC +glXIsDirect(Display *dpy, GLXContext ctx) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->IsDirect)(dpy, ctx); +} + + +Bool PUBLIC +glXMakeCurrent(Display *dpy, GLXDrawable drawable, GLXContext ctx) +{ + Bool b; + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) { + return False; + } + b = (*t->MakeCurrent)(dpy, drawable, ctx); + if (b) { + SetCurrentContext(ctx); + } + return b; +} + + +Bool PUBLIC +glXQueryExtension(Display *dpy, int *errorb, int *event) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->QueryExtension)(dpy, errorb, event); +} + + +Bool PUBLIC +glXQueryVersion(Display *dpy, int *maj, int *min) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->QueryVersion)(dpy, maj, min); +} + + +void PUBLIC +glXSwapBuffers(Display *dpy, GLXDrawable drawable) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->SwapBuffers)(dpy, drawable); +} + + +void PUBLIC +glXUseXFont(Font font, int first, int count, int listBase) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->UseXFont)(font, first, count, listBase); +} + + +void PUBLIC +glXWaitGL(void) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->WaitGL)(); +} + + +void PUBLIC +glXWaitX(void) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->WaitX)(); +} + + + +/*** GLX_VERSION_1_1 ***/ + +const char PUBLIC * +glXGetClientString(Display *dpy, int name) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->GetClientString)(dpy, name); +} + + +const char PUBLIC * +glXQueryExtensionsString(Display *dpy, int screen) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->QueryExtensionsString)(dpy, screen); +} + + +const char PUBLIC * +glXQueryServerString(Display *dpy, int screen, int name) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->QueryServerString)(dpy, screen, name); +} + + +/*** GLX_VERSION_1_2 ***/ + +Display PUBLIC * +glXGetCurrentDisplay(void) +{ + /* Same code as in libGL's glxext.c */ + __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); + if (NULL == gc) return NULL; + return gc->currentDpy; +} + + + +/*** GLX_VERSION_1_3 ***/ + +GLXFBConfig PUBLIC * +glXChooseFBConfig(Display *dpy, int screen, const int *attribList, int *nitems) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ChooseFBConfig)(dpy, screen, attribList, nitems); +} + + +GLXContext PUBLIC +glXCreateNewContext(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateNewContext)(dpy, config, renderType, shareList, direct); +} + + +GLXPbuffer PUBLIC +glXCreatePbuffer(Display *dpy, GLXFBConfig config, const int *attribList) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreatePbuffer)(dpy, config, attribList); +} + + +GLXPixmap PUBLIC +glXCreatePixmap(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreatePixmap)(dpy, config, pixmap, attribList); +} + + +GLXWindow PUBLIC +glXCreateWindow(Display *dpy, GLXFBConfig config, Window win, const int *attribList) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateWindow)(dpy, config, win, attribList); +} + + +void PUBLIC +glXDestroyPbuffer(Display *dpy, GLXPbuffer pbuf) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyPbuffer)(dpy, pbuf); +} + + +void PUBLIC +glXDestroyPixmap(Display *dpy, GLXPixmap pixmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyPixmap)(dpy, pixmap); +} + + +void PUBLIC +glXDestroyWindow(Display *dpy, GLXWindow window) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyWindow)(dpy, window); +} + + +GLXDrawable PUBLIC +glXGetCurrentReadDrawable(void) +{ + __GLXcontext *gc = (__GLXcontext *) glXGetCurrentContext(); + return gc ? gc->currentReadable : 0; +} + + +int PUBLIC +glXGetFBConfigAttrib(Display *dpy, GLXFBConfig config, int attribute, int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return GLX_NO_EXTENSION; + return (t->GetFBConfigAttrib)(dpy, config, attribute, value); +} + + +GLXFBConfig PUBLIC * +glXGetFBConfigs(Display *dpy, int screen, int *nelements) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->GetFBConfigs)(dpy, screen, nelements); +} + +void PUBLIC +glXGetSelectedEvent(Display *dpy, GLXDrawable drawable, unsigned long *mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->GetSelectedEvent)(dpy, drawable, mask); +} + + +XVisualInfo PUBLIC * +glXGetVisualFromFBConfig(Display *dpy, GLXFBConfig config) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return NULL; + return (t->GetVisualFromFBConfig)(dpy, config); +} + + +Bool PUBLIC +glXMakeContextCurrent(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + Bool b; + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + b = (t->MakeContextCurrent)(dpy, draw, read, ctx); + if (b) { + SetCurrentContext(ctx); + } + return b; +} + + +int PUBLIC +glXQueryContext(Display *dpy, GLXContext ctx, int attribute, int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + assert(t); + if (!t) + return 0; /* XXX correct? */ + return (t->QueryContext)(dpy, ctx, attribute, value); +} + + +void PUBLIC +glXQueryDrawable(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->QueryDrawable)(dpy, draw, attribute, value); +} + + +void PUBLIC +glXSelectEvent(Display *dpy, GLXDrawable drawable, unsigned long mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->SelectEvent)(dpy, drawable, mask); +} + + + +/*** GLX_SGI_swap_control ***/ + +int PUBLIC +glXSwapIntervalSGI(int interval) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->SwapIntervalSGI)(interval); +} + + + +/*** GLX_SGI_video_sync ***/ + +int PUBLIC +glXGetVideoSyncSGI(unsigned int *count) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t || !glXGetCurrentContext()) + return GLX_BAD_CONTEXT; + return (t->GetVideoSyncSGI)(count); +} + +int PUBLIC +glXWaitVideoSyncSGI(int divisor, int remainder, unsigned int *count) +{ + struct _glxapi_table *t; + Display *dpy = glXGetCurrentDisplay(); + GET_DISPATCH(dpy, t); + if (!t || !glXGetCurrentContext()) + return GLX_BAD_CONTEXT; + return (t->WaitVideoSyncSGI)(divisor, remainder, count); +} + + + +/*** GLX_SGI_make_current_read ***/ + +Bool PUBLIC +glXMakeCurrentReadSGI(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->MakeCurrentReadSGI)(dpy, draw, read, ctx); +} + +GLXDrawable PUBLIC +glXGetCurrentReadDrawableSGI(void) +{ + return glXGetCurrentReadDrawable(); +} + + +#if defined(_VL_H) + +GLXVideoSourceSGIX PUBLIC +glXCreateGLXVideoSourceSGIX(Display *dpy, int screen, VLServer server, VLPath path, int nodeClass, VLNode drainNode) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXVideoSourceSGIX)(dpy, screen, server, path, nodeClass, drainNode); +} + +void PUBLIC +glXDestroyGLXVideoSourceSGIX(Display *dpy, GLXVideoSourceSGIX src) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->DestroyGLXVideoSourceSGIX)(dpy, src); +} + +#endif + + +/*** GLX_EXT_import_context ***/ + +void PUBLIC +glXFreeContextEXT(Display *dpy, GLXContext context) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->FreeContextEXT)(dpy, context); +} + +GLXContextID PUBLIC +glXGetContextIDEXT(const GLXContext context) +{ + return ((__GLXcontext *) context)->xid; +} + +Display PUBLIC * +glXGetCurrentDisplayEXT(void) +{ + return glXGetCurrentDisplay(); +} + +GLXContext PUBLIC +glXImportContextEXT(Display *dpy, GLXContextID contextID) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ImportContextEXT)(dpy, contextID); +} + +int PUBLIC +glXQueryContextInfoEXT(Display *dpy, GLXContext context, int attribute,int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; /* XXX ok? */ + return (t->QueryContextInfoEXT)(dpy, context, attribute, value); +} + + + +/*** GLX_SGIX_fbconfig ***/ + +int PUBLIC +glXGetFBConfigAttribSGIX(Display *dpy, GLXFBConfigSGIX config, int attribute, int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->GetFBConfigAttribSGIX)(dpy, config, attribute, value); +} + +GLXFBConfigSGIX PUBLIC * +glXChooseFBConfigSGIX(Display *dpy, int screen, int *attrib_list, int *nelements) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ChooseFBConfigSGIX)(dpy, screen, attrib_list, nelements); +} + +GLXPixmap PUBLIC +glXCreateGLXPixmapWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, Pixmap pixmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXPixmapWithConfigSGIX)(dpy, config, pixmap); +} + +GLXContext PUBLIC +glXCreateContextWithConfigSGIX(Display *dpy, GLXFBConfigSGIX config, int render_type, GLXContext share_list, Bool direct) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateContextWithConfigSGIX)(dpy, config, render_type, share_list, direct); +} + +XVisualInfo PUBLIC * +glXGetVisualFromFBConfigSGIX(Display *dpy, GLXFBConfigSGIX config) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->GetVisualFromFBConfigSGIX)(dpy, config); +} + +GLXFBConfigSGIX PUBLIC +glXGetFBConfigFromVisualSGIX(Display *dpy, XVisualInfo *vis) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->GetFBConfigFromVisualSGIX)(dpy, vis); +} + + + +/*** GLX_SGIX_pbuffer ***/ + +GLXPbufferSGIX PUBLIC +glXCreateGLXPbufferSGIX(Display *dpy, GLXFBConfigSGIX config, unsigned int width, unsigned int height, int *attrib_list) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXPbufferSGIX)(dpy, config, width, height, attrib_list); +} + +void PUBLIC +glXDestroyGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->DestroyGLXPbufferSGIX)(dpy, pbuf); +} + +int PUBLIC +glXQueryGLXPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuf, int attribute, unsigned int *value) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->QueryGLXPbufferSGIX)(dpy, pbuf, attribute, value); +} + +void PUBLIC +glXSelectEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->SelectEventSGIX)(dpy, drawable, mask); +} + +void PUBLIC +glXGetSelectedEventSGIX(Display *dpy, GLXDrawable drawable, unsigned long *mask) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->GetSelectedEventSGIX)(dpy, drawable, mask); +} + + + +/*** GLX_SGI_cushion ***/ + +void PUBLIC +glXCushionSGI(Display *dpy, Window win, float cushion) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->CushionSGI)(dpy, win, cushion); +} + + + +/*** GLX_SGIX_video_resize ***/ + +int PUBLIC +glXBindChannelToWindowSGIX(Display *dpy, int screen, int channel , Window window) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->BindChannelToWindowSGIX)(dpy, screen, channel, window); +} + +int PUBLIC +glXChannelRectSGIX(Display *dpy, int screen, int channel, int x, int y, int w, int h) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ChannelRectSGIX)(dpy, screen, channel, x, y, w, h); +} + +int PUBLIC +glXQueryChannelRectSGIX(Display *dpy, int screen, int channel, int *x, int *y, int *w, int *h) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->QueryChannelRectSGIX)(dpy, screen, channel, x, y, w, h); +} + +int PUBLIC +glXQueryChannelDeltasSGIX(Display *dpy, int screen, int channel, int *dx, int *dy, int *dw, int *dh) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->QueryChannelDeltasSGIX)(dpy, screen, channel, dx, dy, dw, dh); +} + +int PUBLIC +glXChannelRectSyncSGIX(Display *dpy, int screen, int channel, GLenum synctype) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->ChannelRectSyncSGIX)(dpy, screen, channel, synctype); +} + + + +#if defined(_DM_BUFFER_H_) + +Bool PUBLIC +glXAssociateDMPbufferSGIX(Display *dpy, GLXPbufferSGIX pbuffer, DMparams *params, DMbuffer dmbuffer) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->AssociateDMPbufferSGIX)(dpy, pbuffer, params, dmbuffer); +} + +#endif + + +/*** GLX_SGIX_swap_group ***/ + +void PUBLIC +glXJoinSwapGroupSGIX(Display *dpy, GLXDrawable drawable, GLXDrawable member) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (*t->JoinSwapGroupSGIX)(dpy, drawable, member); +} + + +/*** GLX_SGIX_swap_barrier ***/ + +void PUBLIC +glXBindSwapBarrierSGIX(Display *dpy, GLXDrawable drawable, int barrier) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (*t->BindSwapBarrierSGIX)(dpy, drawable, barrier); +} + +Bool PUBLIC +glXQueryMaxSwapBarriersSGIX(Display *dpy, int screen, int *max) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (*t->QueryMaxSwapBarriersSGIX)(dpy, screen, max); +} + + + +/*** GLX_SUN_get_transparent_index ***/ + +Status PUBLIC +glXGetTransparentIndexSUN(Display *dpy, Window overlay, Window underlay, long *pTransparent) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (*t->GetTransparentIndexSUN)(dpy, overlay, underlay, pTransparent); +} + + + +/*** GLX_MESA_copy_sub_buffer ***/ + +void PUBLIC +glXCopySubBufferMESA(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return; + (t->CopySubBufferMESA)(dpy, drawable, x, y, width, height); +} + + + +/*** GLX_MESA_release_buffers ***/ + +Bool PUBLIC +glXReleaseBuffersMESA(Display *dpy, Window w) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return False; + return (t->ReleaseBuffersMESA)(dpy, w); +} + + + +/*** GLX_MESA_pixmap_colormap ***/ + +GLXPixmap PUBLIC +glXCreateGLXPixmapMESA(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (!t) + return 0; + return (t->CreateGLXPixmapMESA)(dpy, visinfo, pixmap, cmap); +} + +/*** GLX_EXT_texture_from_pixmap */ + +void +glXBindTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer, + const int *attrib_list) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (t) + t->BindTexImageEXT(dpy, drawable, buffer, attrib_list); +} + +void +glXReleaseTexImageEXT(Display *dpy, GLXDrawable drawable, int buffer) +{ + struct _glxapi_table *t; + GET_DISPATCH(dpy, t); + if (t) + t->ReleaseTexImageEXT(dpy, drawable, buffer); +} + + +/**********************************************************************/ +/* GLX API management functions */ +/**********************************************************************/ + + +const char * +_glxapi_get_version(void) +{ + return "1.3"; +} + + + +/* + * Return size of the GLX dispatch table, in entries, not bytes. + */ +GLuint +_glxapi_get_dispatch_table_size(void) +{ + return sizeof(struct _glxapi_table) / sizeof(void *); +} + + +static int +generic_no_op_func(void) +{ + return 0; +} + + +/* + * Initialize all functions in given dispatch table to be no-ops + */ +void +_glxapi_set_no_op_table(struct _glxapi_table *t) +{ + typedef int (*nop_func)(void); + nop_func *dispatch = (nop_func *) t; + GLuint n = _glxapi_get_dispatch_table_size(); + GLuint i; + for (i = 0; i < n; i++) { + dispatch[i] = generic_no_op_func; + } +} + + +struct name_address_pair { + const char *Name; + __GLXextFuncPtr Address; +}; + +static struct name_address_pair GLX_functions[] = { + /*** GLX_VERSION_1_0 ***/ + { "glXChooseVisual", (__GLXextFuncPtr) glXChooseVisual }, + { "glXCopyContext", (__GLXextFuncPtr) glXCopyContext }, + { "glXCreateContext", (__GLXextFuncPtr) glXCreateContext }, + { "glXCreateGLXPixmap", (__GLXextFuncPtr) glXCreateGLXPixmap }, + { "glXDestroyContext", (__GLXextFuncPtr) glXDestroyContext }, + { "glXDestroyGLXPixmap", (__GLXextFuncPtr) glXDestroyGLXPixmap }, + { "glXGetConfig", (__GLXextFuncPtr) glXGetConfig }, + { "glXGetCurrentContext", (__GLXextFuncPtr) glXGetCurrentContext }, + { "glXGetCurrentDrawable", (__GLXextFuncPtr) glXGetCurrentDrawable }, + { "glXIsDirect", (__GLXextFuncPtr) glXIsDirect }, + { "glXMakeCurrent", (__GLXextFuncPtr) glXMakeCurrent }, + { "glXQueryExtension", (__GLXextFuncPtr) glXQueryExtension }, + { "glXQueryVersion", (__GLXextFuncPtr) glXQueryVersion }, + { "glXSwapBuffers", (__GLXextFuncPtr) glXSwapBuffers }, + { "glXUseXFont", (__GLXextFuncPtr) glXUseXFont }, + { "glXWaitGL", (__GLXextFuncPtr) glXWaitGL }, + { "glXWaitX", (__GLXextFuncPtr) glXWaitX }, + + /*** GLX_VERSION_1_1 ***/ + { "glXGetClientString", (__GLXextFuncPtr) glXGetClientString }, + { "glXQueryExtensionsString", (__GLXextFuncPtr) glXQueryExtensionsString }, + { "glXQueryServerString", (__GLXextFuncPtr) glXQueryServerString }, + + /*** GLX_VERSION_1_2 ***/ + { "glXGetCurrentDisplay", (__GLXextFuncPtr) glXGetCurrentDisplay }, + + /*** GLX_VERSION_1_3 ***/ + { "glXChooseFBConfig", (__GLXextFuncPtr) glXChooseFBConfig }, + { "glXCreateNewContext", (__GLXextFuncPtr) glXCreateNewContext }, + { "glXCreatePbuffer", (__GLXextFuncPtr) glXCreatePbuffer }, + { "glXCreatePixmap", (__GLXextFuncPtr) glXCreatePixmap }, + { "glXCreateWindow", (__GLXextFuncPtr) glXCreateWindow }, + { "glXDestroyPbuffer", (__GLXextFuncPtr) glXDestroyPbuffer }, + { "glXDestroyPixmap", (__GLXextFuncPtr) glXDestroyPixmap }, + { "glXDestroyWindow", (__GLXextFuncPtr) glXDestroyWindow }, + { "glXGetCurrentReadDrawable", (__GLXextFuncPtr) glXGetCurrentReadDrawable }, + { "glXGetFBConfigAttrib", (__GLXextFuncPtr) glXGetFBConfigAttrib }, + { "glXGetFBConfigs", (__GLXextFuncPtr) glXGetFBConfigs }, + { "glXGetSelectedEvent", (__GLXextFuncPtr) glXGetSelectedEvent }, + { "glXGetVisualFromFBConfig", (__GLXextFuncPtr) glXGetVisualFromFBConfig }, + { "glXMakeContextCurrent", (__GLXextFuncPtr) glXMakeContextCurrent }, + { "glXQueryContext", (__GLXextFuncPtr) glXQueryContext }, + { "glXQueryDrawable", (__GLXextFuncPtr) glXQueryDrawable }, + { "glXSelectEvent", (__GLXextFuncPtr) glXSelectEvent }, + + /*** GLX_VERSION_1_4 ***/ + { "glXGetProcAddress", (__GLXextFuncPtr) glXGetProcAddress }, + + /*** GLX_SGI_swap_control ***/ + { "glXSwapIntervalSGI", (__GLXextFuncPtr) glXSwapIntervalSGI }, + + /*** GLX_SGI_video_sync ***/ + { "glXGetVideoSyncSGI", (__GLXextFuncPtr) glXGetVideoSyncSGI }, + { "glXWaitVideoSyncSGI", (__GLXextFuncPtr) glXWaitVideoSyncSGI }, + + /*** GLX_SGI_make_current_read ***/ + { "glXMakeCurrentReadSGI", (__GLXextFuncPtr) glXMakeCurrentReadSGI }, + { "glXGetCurrentReadDrawableSGI", (__GLXextFuncPtr) glXGetCurrentReadDrawableSGI }, + + /*** GLX_SGIX_video_source ***/ +#if defined(_VL_H) + { "glXCreateGLXVideoSourceSGIX", (__GLXextFuncPtr) glXCreateGLXVideoSourceSGIX }, + { "glXDestroyGLXVideoSourceSGIX", (__GLXextFuncPtr) glXDestroyGLXVideoSourceSGIX }, +#endif + + /*** GLX_EXT_import_context ***/ + { "glXFreeContextEXT", (__GLXextFuncPtr) glXFreeContextEXT }, + { "glXGetContextIDEXT", (__GLXextFuncPtr) glXGetContextIDEXT }, + { "glXGetCurrentDisplayEXT", (__GLXextFuncPtr) glXGetCurrentDisplayEXT }, + { "glXImportContextEXT", (__GLXextFuncPtr) glXImportContextEXT }, + { "glXQueryContextInfoEXT", (__GLXextFuncPtr) glXQueryContextInfoEXT }, + + /*** GLX_SGIX_fbconfig ***/ + { "glXGetFBConfigAttribSGIX", (__GLXextFuncPtr) glXGetFBConfigAttribSGIX }, + { "glXChooseFBConfigSGIX", (__GLXextFuncPtr) glXChooseFBConfigSGIX }, + { "glXCreateGLXPixmapWithConfigSGIX", (__GLXextFuncPtr) glXCreateGLXPixmapWithConfigSGIX }, + { "glXCreateContextWithConfigSGIX", (__GLXextFuncPtr) glXCreateContextWithConfigSGIX }, + { "glXGetVisualFromFBConfigSGIX", (__GLXextFuncPtr) glXGetVisualFromFBConfigSGIX }, + { "glXGetFBConfigFromVisualSGIX", (__GLXextFuncPtr) glXGetFBConfigFromVisualSGIX }, + + /*** GLX_SGIX_pbuffer ***/ + { "glXCreateGLXPbufferSGIX", (__GLXextFuncPtr) glXCreateGLXPbufferSGIX }, + { "glXDestroyGLXPbufferSGIX", (__GLXextFuncPtr) glXDestroyGLXPbufferSGIX }, + { "glXQueryGLXPbufferSGIX", (__GLXextFuncPtr) glXQueryGLXPbufferSGIX }, + { "glXSelectEventSGIX", (__GLXextFuncPtr) glXSelectEventSGIX }, + { "glXGetSelectedEventSGIX", (__GLXextFuncPtr) glXGetSelectedEventSGIX }, + + /*** GLX_SGI_cushion ***/ + { "glXCushionSGI", (__GLXextFuncPtr) glXCushionSGI }, + + /*** GLX_SGIX_video_resize ***/ + { "glXBindChannelToWindowSGIX", (__GLXextFuncPtr) glXBindChannelToWindowSGIX }, + { "glXChannelRectSGIX", (__GLXextFuncPtr) glXChannelRectSGIX }, + { "glXQueryChannelRectSGIX", (__GLXextFuncPtr) glXQueryChannelRectSGIX }, + { "glXQueryChannelDeltasSGIX", (__GLXextFuncPtr) glXQueryChannelDeltasSGIX }, + { "glXChannelRectSyncSGIX", (__GLXextFuncPtr) glXChannelRectSyncSGIX }, + + /*** GLX_SGIX_dmbuffer **/ +#if defined(_DM_BUFFER_H_) + { "glXAssociateDMPbufferSGIX", (__GLXextFuncPtr) glXAssociateDMPbufferSGIX }, +#endif + + /*** GLX_SGIX_swap_group ***/ + { "glXJoinSwapGroupSGIX", (__GLXextFuncPtr) glXJoinSwapGroupSGIX }, + + /*** GLX_SGIX_swap_barrier ***/ + { "glXBindSwapBarrierSGIX", (__GLXextFuncPtr) glXBindSwapBarrierSGIX }, + { "glXQueryMaxSwapBarriersSGIX", (__GLXextFuncPtr) glXQueryMaxSwapBarriersSGIX }, + + /*** GLX_SUN_get_transparent_index ***/ + { "glXGetTransparentIndexSUN", (__GLXextFuncPtr) glXGetTransparentIndexSUN }, + + /*** GLX_MESA_copy_sub_buffer ***/ + { "glXCopySubBufferMESA", (__GLXextFuncPtr) glXCopySubBufferMESA }, + + /*** GLX_MESA_pixmap_colormap ***/ + { "glXCreateGLXPixmapMESA", (__GLXextFuncPtr) glXCreateGLXPixmapMESA }, + + /*** GLX_MESA_release_buffers ***/ + { "glXReleaseBuffersMESA", (__GLXextFuncPtr) glXReleaseBuffersMESA }, + + /*** GLX_ARB_get_proc_address ***/ + { "glXGetProcAddressARB", (__GLXextFuncPtr) glXGetProcAddressARB }, + + /*** GLX_EXT_texture_from_pixmap ***/ + { "glXBindTexImageEXT", (__GLXextFuncPtr) glXBindTexImageEXT }, + { "glXReleaseTexImageEXT", (__GLXextFuncPtr) glXReleaseTexImageEXT }, + + { NULL, NULL } /* end of list */ +}; + + + +/* + * Return address of named glX function, or NULL if not found. + */ +__GLXextFuncPtr +_glxapi_get_proc_address(const char *funcName) +{ + GLuint i; + for (i = 0; GLX_functions[i].Name; i++) { + if (strcmp(GLX_functions[i].Name, funcName) == 0) + return GLX_functions[i].Address; + } + return NULL; +} + + + +/* + * This function does not get dispatched through the dispatch table + * since it's really a "meta" function. + */ +__GLXextFuncPtr +glXGetProcAddressARB(const GLubyte *procName) +{ + __GLXextFuncPtr f; + + f = _glxapi_get_proc_address((const char *) procName); + if (f) { + return f; + } + + f = (__GLXextFuncPtr) _glapi_get_proc_address((const char *) procName); + return f; +} + + +/* GLX 1.4 */ +void (*glXGetProcAddress(const GLubyte *procName))() +{ + return glXGetProcAddressARB(procName); +} diff --git a/src/gallium/state_trackers/glx/xlib/glxapi.h b/src/gallium/state_trackers/glx/xlib/glxapi.h new file mode 100644 index 00000000000..b4e12b4162b --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/glxapi.h @@ -0,0 +1,213 @@ +/* + * Mesa 3-D graphics library + * Version: 6.3 + * + * Copyright (C) 1999-2004 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + +#ifndef _glxapi_h_ +#define _glxapi_h_ + + +#define GLX_GLXEXT_PROTOTYPES +#include "GL/glx.h" + + +/* The GLX API dispatcher (i.e. this code) is being built into stand-alone + * Mesa. We don't know anything about XFree86 or real GLX so we define a + * minimal __GLXContextRec here so some of the functions in this file can + * work properly. + */ +typedef struct __GLXcontextRec { + Display *currentDpy; + GLboolean isDirect; + GLXDrawable currentDrawable; + GLXDrawable currentReadable; + XID xid; +} __GLXcontext; + + +/* + * Almost all the GLX API functions get routed through this dispatch table. + * The exceptions are the glXGetCurrentXXX() functions. + * + * This dispatch table allows multiple GLX client-side modules to coexist. + * Specifically, a real GLX library (like SGI's or the Utah GLX) and Mesa's + * pseudo-GLX can be present at the same time. The former being used on + * GLX-enabled X servers and the later on non-GLX X servers. + * + * Red Hat has been using this since Red Hat Linux 7.0 (I think). + * This'll be a standard feature in XFree86 4.3. It basically allows one + * libGL to do both DRI-rendering and "fake GLX" rendering to X displays + * that lack the GLX extension. + */ +struct _glxapi_table { + /*** GLX_VERSION_1_0 ***/ + XVisualInfo *(*ChooseVisual)(Display *dpy, int screen, int *list); + void (*CopyContext)(Display *dpy, GLXContext src, GLXContext dst, unsigned long mask); + GLXContext (*CreateContext)(Display *dpy, XVisualInfo *visinfo, GLXContext shareList, Bool direct); + GLXPixmap (*CreateGLXPixmap)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap); + void (*DestroyContext)(Display *dpy, GLXContext ctx); + void (*DestroyGLXPixmap)(Display *dpy, GLXPixmap pixmap); + int (*GetConfig)(Display *dpy, XVisualInfo *visinfo, int attrib, int *value); + /*GLXContext (*GetCurrentContext)(void);*/ + /*GLXDrawable (*GetCurrentDrawable)(void);*/ + Bool (*IsDirect)(Display *dpy, GLXContext ctx); + Bool (*MakeCurrent)(Display *dpy, GLXDrawable drawable, GLXContext ctx); + Bool (*QueryExtension)(Display *dpy, int *errorb, int *event); + Bool (*QueryVersion)(Display *dpy, int *maj, int *min); + void (*SwapBuffers)(Display *dpy, GLXDrawable drawable); + void (*UseXFont)(Font font, int first, int count, int listBase); + void (*WaitGL)(void); + void (*WaitX)(void); + + /*** GLX_VERSION_1_1 ***/ + const char *(*GetClientString)(Display *dpy, int name); + const char *(*QueryExtensionsString)(Display *dpy, int screen); + const char *(*QueryServerString)(Display *dpy, int screen, int name); + + /*** GLX_VERSION_1_2 ***/ + /*Display *(*GetCurrentDisplay)(void);*/ + + /*** GLX_VERSION_1_3 ***/ + GLXFBConfig *(*ChooseFBConfig)(Display *dpy, int screen, const int *attribList, int *nitems); + GLXContext (*CreateNewContext)(Display *dpy, GLXFBConfig config, int renderType, GLXContext shareList, Bool direct); + GLXPbuffer (*CreatePbuffer)(Display *dpy, GLXFBConfig config, const int *attribList); + GLXPixmap (*CreatePixmap)(Display *dpy, GLXFBConfig config, Pixmap pixmap, const int *attribList); + GLXWindow (*CreateWindow)(Display *dpy, GLXFBConfig config, Window win, const int *attribList); + void (*DestroyPbuffer)(Display *dpy, GLXPbuffer pbuf); + void (*DestroyPixmap)(Display *dpy, GLXPixmap pixmap); + void (*DestroyWindow)(Display *dpy, GLXWindow window); + /*GLXDrawable (*GetCurrentReadDrawable)(void);*/ + int (*GetFBConfigAttrib)(Display *dpy, GLXFBConfig config, int attribute, int *value); + GLXFBConfig *(*GetFBConfigs)(Display *dpy, int screen, int *nelements); + void (*GetSelectedEvent)(Display *dpy, GLXDrawable drawable, unsigned long *mask); + XVisualInfo *(*GetVisualFromFBConfig)(Display *dpy, GLXFBConfig config); + Bool (*MakeContextCurrent)(Display *dpy, GLXDrawable draw, GLXDrawable read, GLXContext ctx); + int (*QueryContext)(Display *dpy, GLXContext ctx, int attribute, int *value); + void (*QueryDrawable)(Display *dpy, GLXDrawable draw, int attribute, unsigned int *value); + void (*SelectEvent)(Display *dpy, GLXDrawable drawable, unsigned long mask); + + /*** GLX_SGI_swap_control ***/ + int (*SwapIntervalSGI)(int); + + /*** GLX_SGI_video_sync ***/ + int (*GetVideoSyncSGI)(unsigned int *count); + int (*WaitVideoSyncSGI)(int divisor, int remainder, unsigned int *count); + + /*** GLX_SGI_make_current_read ***/ + Bool (*MakeCurrentReadSGI)(Display *, GLXDrawable, GLXDrawable, GLXContext); + /*GLXDrawable (*GetCurrentReadDrawableSGI)(void);*/ + + /*** GLX_SGIX_video_source (needs video library) ***/ +#if defined(_VL_H_) + GLXVideoSourceSGIX (*CreateGLXVideoSourceSGIX)(Display *, int, VLServer, VLPath, int, VLNode); + void (*DestroyGLXVideoSourceSGIX)(Display *, GLXVideoSourceSGIX); +#else + void *CreateGLXVideoSourceSGIX; + void *DestroyGLXVideoSourceSGIX; +#endif + + /*** GLX_EXT_import_context ***/ + void (*FreeContextEXT)(Display *dpy, GLXContext context); + GLXContextID (*GetContextIDEXT)(const GLXContext context); + /*Display *(*GetCurrentDisplayEXT)(void);*/ + GLXContext (*ImportContextEXT)(Display *dpy, GLXContextID contextID); + int (*QueryContextInfoEXT)(Display *dpy, GLXContext context, int attribute,int *value); + + /*** GLX_SGIX_fbconfig ***/ + int (*GetFBConfigAttribSGIX)(Display *, GLXFBConfigSGIX, int, int *); + GLXFBConfigSGIX * (*ChooseFBConfigSGIX)(Display *, int, int *, int *); + GLXPixmap (*CreateGLXPixmapWithConfigSGIX)(Display *, GLXFBConfigSGIX, Pixmap); + GLXContext (*CreateContextWithConfigSGIX)(Display *, GLXFBConfigSGIX, int, GLXContext, Bool); + XVisualInfo * (*GetVisualFromFBConfigSGIX)(Display *, GLXFBConfigSGIX); + GLXFBConfigSGIX (*GetFBConfigFromVisualSGIX)(Display *, XVisualInfo *); + + /*** GLX_SGIX_pbuffer ***/ + GLXPbufferSGIX (*CreateGLXPbufferSGIX)(Display *, GLXFBConfigSGIX, unsigned int, unsigned int, int *); + void (*DestroyGLXPbufferSGIX)(Display *, GLXPbufferSGIX); + int (*QueryGLXPbufferSGIX)(Display *, GLXPbufferSGIX, int, unsigned int *); + void (*SelectEventSGIX)(Display *, GLXDrawable, unsigned long); + void (*GetSelectedEventSGIX)(Display *, GLXDrawable, unsigned long *); + + /*** GLX_SGI_cushion ***/ + void (*CushionSGI)(Display *, Window, float); + + /*** GLX_SGIX_video_resize ***/ + int (*BindChannelToWindowSGIX)(Display *, int, int, Window); + int (*ChannelRectSGIX)(Display *, int, int, int, int, int, int); + int (*QueryChannelRectSGIX)(Display *, int, int, int *, int *, int *, int *); + int (*QueryChannelDeltasSGIX)(Display *, int, int, int *, int *, int *, int *); + int (*ChannelRectSyncSGIX)(Display *, int, int, GLenum); + + /*** GLX_SGIX_dmbuffer (needs dmedia library) ***/ +#if defined (_DM_BUFFER_H_) + Bool (*AssociateDMPbufferSGIX)(Display *, GLXPbufferSGIX, DMparams *, DMbuffer); +#else + void *AssociciateDMPbufferSGIX; +#endif + + /*** GLX_SGIX_swap_group ***/ + void (*JoinSwapGroupSGIX)(Display *, GLXDrawable, GLXDrawable); + + /*** GLX_SGIX_swap_barrier ***/ + void (*BindSwapBarrierSGIX)(Display *, GLXDrawable, int); + Bool (*QueryMaxSwapBarriersSGIX)(Display *, int, int *); + + /*** GLX_SUN_get_transparent_index ***/ + Status (*GetTransparentIndexSUN)(Display *, Window, Window, long *); + + /*** GLX_MESA_copy_sub_buffer ***/ + void (*CopySubBufferMESA)(Display *dpy, GLXDrawable drawable, int x, int y, int width, int height); + + /*** GLX_MESA_release_buffers ***/ + Bool (*ReleaseBuffersMESA)(Display *dpy, Window w); + + /*** GLX_MESA_pixmap_colormap ***/ + GLXPixmap (*CreateGLXPixmapMESA)(Display *dpy, XVisualInfo *visinfo, Pixmap pixmap, Colormap cmap); + + /*** GLX_EXT_texture_from_pixmap ***/ + void (*BindTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer, + const int *attrib_list); + void (*ReleaseTexImageEXT)(Display *dpy, GLXDrawable drawable, int buffer); +}; + + + +extern const char * +_glxapi_get_version(void); + + + + +extern GLuint +_glxapi_get_dispatch_table_size(void); + + +extern void +_glxapi_set_no_op_table(struct _glxapi_table *t); + + +extern __GLXextFuncPtr +_glxapi_get_proc_address(const char *funcName); + + +#endif diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.c b/src/gallium/state_trackers/glx/xlib/xm_api.c new file mode 100644 index 00000000000..33dc044ad55 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_api.c @@ -0,0 +1,1230 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + +/** + * \file xm_api.c + * + * All the XMesa* API functions. + * + * + * NOTES: + * + * The window coordinate system origin (0,0) is in the lower-left corner + * of the window. X11's window coordinate origin is in the upper-left + * corner of the window. Therefore, most drawing functions in this + * file have to flip Y coordinates. + * + * Define USE_XSHM in the Makefile with -DUSE_XSHM if you want to compile + * in support for the MIT Shared Memory extension. If enabled, when you + * use an Ximage for the back buffer in double buffered mode, the "swap" + * operation will be faster. You must also link with -lXext. + * + * Byte swapping: If the Mesa host and the X display use a different + * byte order then there's some trickiness to be aware of when using + * XImages. The byte ordering used for the XImage is that of the X + * display, not the Mesa host. + * The color-to-pixel encoding for True/DirectColor must be done + * according to the display's visual red_mask, green_mask, and blue_mask. + * If XPutPixel is used to put a pixel into an XImage then XPutPixel will + * do byte swapping if needed. If one wants to directly "poke" the pixel + * into the XImage's buffer then the pixel must be byte swapped first. + * + */ + +#ifdef __CYGWIN__ +#undef WIN32 +#undef __WIN32__ +#endif + +#include "xm_api.h" +#include "main/context.h" +#include "main/framebuffer.h" + +#include "state_tracker/st_public.h" +#include "state_tracker/st_context.h" +#include "pipe/p_defines.h" +#include "pipe/p_screen.h" +#include "pipe/p_context.h" + +#include "xm_winsys.h" +#include <GL/glx.h> + + +/* Driver interface routines, set up by xlib backend on library + * _init(). These are global in the same way that function names are + * global. + */ +static struct xm_driver driver; + +void xmesa_set_driver( const struct xm_driver *templ ) +{ + driver = *templ; +} + +/** + * Global X driver lock + */ +pipe_mutex _xmesa_lock; + + + +/**********************************************************************/ +/***** X Utility Functions *****/ +/**********************************************************************/ + + +/** + * Return the host's byte order as LSBFirst or MSBFirst ala X. + */ +static int host_byte_order( void ) +{ + int i = 1; + char *cptr = (char *) &i; + return (*cptr==1) ? LSBFirst : MSBFirst; +} + + +/** + * Check if the X Shared Memory extension is available. + * Return: 0 = not available + * 1 = shared XImage support available + * 2 = shared Pixmap support available also + */ +int xmesa_check_for_xshm( Display *display ) +{ +#if defined(USE_XSHM) + int major, minor, ignore; + Bool pixmaps; + + if (getenv("SP_NO_RAST")) + return 0; + + if (getenv("MESA_NOSHM")) { + return 0; + } + + if (XQueryExtension( display, "MIT-SHM", &ignore, &ignore, &ignore )) { + if (XShmQueryVersion( display, &major, &minor, &pixmaps )==True) { + return (pixmaps==True) ? 2 : 1; + } + else { + return 0; + } + } + else { + return 0; + } +#else + /* No XSHM support */ + return 0; +#endif +} + + +/** + * Return the true number of bits per pixel for XImages. + * For example, if we request a 24-bit deep visual we may actually need/get + * 32bpp XImages. This function returns the appropriate bpp. + * Input: dpy - the X display + * visinfo - desribes the visual to be used for XImages + * Return: true number of bits per pixel for XImages + */ +static int +bits_per_pixel( XMesaVisual xmv ) +{ + Display *dpy = xmv->display; + XVisualInfo * visinfo = xmv->visinfo; + XImage *img; + int bitsPerPixel; + /* Create a temporary XImage */ + img = XCreateImage( dpy, visinfo->visual, visinfo->depth, + ZPixmap, 0, /*format, offset*/ + (char*) MALLOC(8), /*data*/ + 1, 1, /*width, height*/ + 32, /*bitmap_pad*/ + 0 /*bytes_per_line*/ + ); + assert(img); + /* grab the bits/pixel value */ + bitsPerPixel = img->bits_per_pixel; + /* free the XImage */ + _mesa_free( img->data ); + img->data = NULL; + XDestroyImage( img ); + return bitsPerPixel; +} + + + +/* + * Determine if a given X window ID is valid (window exists). + * Do this by calling XGetWindowAttributes() for the window and + * checking if we catch an X error. + * Input: dpy - the display + * win - the window to check for existance + * Return: GL_TRUE - window exists + * GL_FALSE - window doesn't exist + */ +static GLboolean WindowExistsFlag; + +static int window_exists_err_handler( Display* dpy, XErrorEvent* xerr ) +{ + (void) dpy; + if (xerr->error_code == BadWindow) { + WindowExistsFlag = GL_FALSE; + } + return 0; +} + +static GLboolean window_exists( Display *dpy, Window win ) +{ + XWindowAttributes wa; + int (*old_handler)( Display*, XErrorEvent* ); + WindowExistsFlag = GL_TRUE; + old_handler = XSetErrorHandler(window_exists_err_handler); + XGetWindowAttributes( dpy, win, &wa ); /* dummy request */ + XSetErrorHandler(old_handler); + return WindowExistsFlag; +} + +static Status +get_drawable_size( Display *dpy, Drawable d, uint *width, uint *height ) +{ + Window root; + Status stat; + int xpos, ypos; + unsigned int w, h, bw, depth; + stat = XGetGeometry(dpy, d, &root, &xpos, &ypos, &w, &h, &bw, &depth); + *width = w; + *height = h; + return stat; +} + + +/** + * Return the size of the window (or pixmap) that corresponds to the + * given XMesaBuffer. + * \param width returns width in pixels + * \param height returns height in pixels + */ +static void +xmesa_get_window_size(Display *dpy, XMesaBuffer b, + GLuint *width, GLuint *height) +{ + Status stat; + + pipe_mutex_lock(_xmesa_lock); + XSync(b->xm_visual->display, 0); /* added for Chromium */ + stat = get_drawable_size(dpy, b->drawable, width, height); + pipe_mutex_unlock(_xmesa_lock); + + if (!stat) { + /* probably querying a window that's recently been destroyed */ + _mesa_warning(NULL, "XGetGeometry failed!\n"); + *width = *height = 1; + } +} + +#define GET_REDMASK(__v) __v->mesa_visual.redMask +#define GET_GREENMASK(__v) __v->mesa_visual.greenMask +#define GET_BLUEMASK(__v) __v->mesa_visual.blueMask + + +/** + * Choose the pixel format for the given visual. + * This will tell the gallium driver how to pack pixel data into + * drawing surfaces. + */ +static GLuint +choose_pixel_format(XMesaVisual v) +{ + boolean native_byte_order = (host_byte_order() == + ImageByteOrder(v->display)); + + if ( GET_REDMASK(v) == 0x0000ff + && GET_GREENMASK(v) == 0x00ff00 + && GET_BLUEMASK(v) == 0xff0000 + && v->BitsPerPixel == 32) { + if (native_byte_order) { + /* no byteswapping needed */ + return 0 /* PIXEL_FORMAT_U_A8_B8_G8_R8 */; + } + else { + return PIPE_FORMAT_R8G8B8A8_UNORM; + } + } + else if ( GET_REDMASK(v) == 0xff0000 + && GET_GREENMASK(v) == 0x00ff00 + && GET_BLUEMASK(v) == 0x0000ff + && v->BitsPerPixel == 32) { + if (native_byte_order) { + /* no byteswapping needed */ + return PIPE_FORMAT_A8R8G8B8_UNORM; + } + else { + return PIPE_FORMAT_B8G8R8A8_UNORM; + } + } + else if ( GET_REDMASK(v) == 0xf800 + && GET_GREENMASK(v) == 0x07e0 + && GET_BLUEMASK(v) == 0x001f + && native_byte_order + && v->BitsPerPixel == 16) { + /* 5-6-5 RGB */ + return PIPE_FORMAT_R5G6B5_UNORM; + } + + assert(0); + return 0; +} + + + +/**********************************************************************/ +/***** Linked list of XMesaBuffers *****/ +/**********************************************************************/ + +XMesaBuffer XMesaBufferList = NULL; + + +/** + * Allocate a new XMesaBuffer object which corresponds to the given drawable. + * Note that XMesaBuffer is derived from GLframebuffer. + * The new XMesaBuffer will not have any size (Width=Height=0). + * + * \param d the corresponding X drawable (window or pixmap) + * \param type either WINDOW, PIXMAP or PBUFFER, describing d + * \param vis the buffer's visual + * \param cmap the window's colormap, if known. + * \return new XMesaBuffer or NULL if any problem + */ +static XMesaBuffer +create_xmesa_buffer(Drawable d, BufferType type, + XMesaVisual vis, Colormap cmap) +{ + XMesaBuffer b; + GLframebuffer *fb; + enum pipe_format colorFormat, depthFormat, stencilFormat; + uint width, height; + + ASSERT(type == WINDOW || type == PIXMAP || type == PBUFFER); + + b = (XMesaBuffer) CALLOC_STRUCT(xmesa_buffer); + if (!b) + return NULL; + + b->drawable = d; + + b->xm_visual = vis; + b->type = type; + b->cmap = cmap; + + /* determine PIPE_FORMATs for buffers */ + colorFormat = choose_pixel_format(vis); + + if (vis->mesa_visual.depthBits == 0) + depthFormat = PIPE_FORMAT_NONE; +#ifdef GALLIUM_CELL /* XXX temporary for Cell! */ + else + depthFormat = PIPE_FORMAT_S8Z24_UNORM; +#else + else if (vis->mesa_visual.depthBits <= 16) + depthFormat = PIPE_FORMAT_Z16_UNORM; + else if (vis->mesa_visual.depthBits <= 24) + depthFormat = PIPE_FORMAT_S8Z24_UNORM; + else + depthFormat = PIPE_FORMAT_Z32_UNORM; +#endif + + if (vis->mesa_visual.stencilBits == 8) { + if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) + stencilFormat = depthFormat; + else + stencilFormat = PIPE_FORMAT_S8_UNORM; + } + else { + /* no stencil */ + stencilFormat = PIPE_FORMAT_NONE; + if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) { + /* use 24-bit Z, undefined stencil channel */ + depthFormat = PIPE_FORMAT_X8Z24_UNORM; + } + } + + + get_drawable_size(vis->display, d, &width, &height); + + /* + * Create framebuffer, but we'll plug in our own renderbuffers below. + */ + b->stfb = st_create_framebuffer(&vis->mesa_visual, + colorFormat, depthFormat, stencilFormat, + width, height, + (void *) b); + fb = &b->stfb->Base; + + /* + * Create scratch XImage for xmesa_display_surface() + */ + b->tempImage = XCreateImage(vis->display, + vis->visinfo->visual, + vis->visinfo->depth, + ZPixmap, 0, /* format, offset */ + NULL, /* data */ + 0, 0, /* size */ + 32, /* bitmap_pad */ + 0); /* bytes_per_line */ + + /* GLX_EXT_texture_from_pixmap */ + b->TextureTarget = 0; + b->TextureFormat = GLX_TEXTURE_FORMAT_NONE_EXT; + b->TextureMipmap = 0; + + /* insert buffer into linked list */ + b->Next = XMesaBufferList; + XMesaBufferList = b; + + return b; +} + + +/** + * Find an XMesaBuffer by matching X display and colormap but NOT matching + * the notThis buffer. + */ +XMesaBuffer +xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis) +{ + XMesaBuffer b; + for (b = XMesaBufferList; b; b = b->Next) { + if (b->xm_visual->display == dpy && + b->cmap == cmap && + b != notThis) { + return b; + } + } + return NULL; +} + + +/** + * Remove buffer from linked list, delete if no longer referenced. + */ +static void +xmesa_free_buffer(XMesaBuffer buffer) +{ + XMesaBuffer prev = NULL, b; + + for (b = XMesaBufferList; b; b = b->Next) { + if (b == buffer) { + struct gl_framebuffer *fb = &buffer->stfb->Base; + + /* unlink buffer from list */ + if (prev) + prev->Next = buffer->Next; + else + XMesaBufferList = buffer->Next; + + /* mark as delete pending */ + fb->DeletePending = GL_TRUE; + + /* Since the X window for the XMesaBuffer is going away, we don't + * want to dereference this pointer in the future. + */ + b->drawable = 0; + + buffer->tempImage->data = NULL; + XDestroyImage(buffer->tempImage); + + /* Unreference. If count = zero we'll really delete the buffer */ + _mesa_unreference_framebuffer(&fb); + + XFreeGC(b->xm_visual->display, b->gc); + + free(buffer); + + return; + } + /* continue search */ + prev = b; + } + /* buffer not found in XMesaBufferList */ + _mesa_problem(NULL,"xmesa_free_buffer() - buffer not found\n"); +} + + + +/**********************************************************************/ +/***** Misc Private Functions *****/ +/**********************************************************************/ + + +/** + * When a context is bound for the first time, we can finally finish + * initializing the context's visual and buffer information. + * \param v the XMesaVisual to initialize + * \param b the XMesaBuffer to initialize (may be NULL) + * \param rgb_flag TRUE = RGBA mode, FALSE = color index mode + * \param window the window/pixmap we're rendering into + * \param cmap the colormap associated with the window/pixmap + * \return GL_TRUE=success, GL_FALSE=failure + */ +static GLboolean +initialize_visual_and_buffer(XMesaVisual v, XMesaBuffer b, + GLboolean rgb_flag, Drawable window, + Colormap cmap) +{ + ASSERT(!b || b->xm_visual == v); + + /* Save true bits/pixel */ + v->BitsPerPixel = bits_per_pixel(v); + assert(v->BitsPerPixel > 0); + + if (rgb_flag == GL_FALSE) { + /* COLOR-INDEXED WINDOW: not supported*/ + return GL_FALSE; + } + else { + /* RGB WINDOW: + * We support RGB rendering into almost any kind of visual. + */ + const int xclass = v->mesa_visual.visualType; + if (xclass != GLX_TRUE_COLOR && xclass == !GLX_DIRECT_COLOR) { + _mesa_warning(NULL, + "XMesa: RGB mode rendering not supported in given visual.\n"); + return GL_FALSE; + } + v->mesa_visual.indexBits = 0; + + if (v->BitsPerPixel == 32) { + /* We use XImages for all front/back buffers. If an X Window or + * X Pixmap is 32bpp, there's no guarantee that the alpha channel + * will be preserved. For XImages we're in luck. + */ + v->mesa_visual.alphaBits = 8; + } + } + + /* + * If MESA_INFO env var is set print out some debugging info + * which can help Brian figure out what's going on when a user + * reports bugs. + */ + if (_mesa_getenv("MESA_INFO")) { + _mesa_printf("X/Mesa visual = %p\n", (void *) v); + _mesa_printf("X/Mesa level = %d\n", v->mesa_visual.level); + _mesa_printf("X/Mesa depth = %d\n", v->visinfo->depth); + _mesa_printf("X/Mesa bits per pixel = %d\n", v->BitsPerPixel); + } + + if (b && window) { + /* these should have been set in create_xmesa_buffer */ + ASSERT(b->drawable == window); + + /* Setup for single/double buffering */ + if (v->mesa_visual.doubleBufferMode) { + /* Double buffered */ + b->shm = xmesa_check_for_xshm( v->display ); + } + + /* X11 graphics context */ + b->gc = XCreateGC( v->display, window, 0, NULL ); + XSetFunction( v->display, b->gc, GXcopy ); + } + + return GL_TRUE; +} + + + +#define NUM_VISUAL_TYPES 6 + +/** + * Convert an X visual type to a GLX visual type. + * + * \param visualType X visual type (i.e., \c TrueColor, \c StaticGray, etc.) + * to be converted. + * \return If \c visualType is a valid X visual type, a GLX visual type will + * be returned. Otherwise \c GLX_NONE will be returned. + * + * \note + * This code was lifted directly from lib/GL/glx/glcontextmodes.c in the + * DRI CVS tree. + */ +static GLint +xmesa_convert_from_x_visual_type( int visualType ) +{ + static const int glx_visual_types[ NUM_VISUAL_TYPES ] = { + GLX_STATIC_GRAY, GLX_GRAY_SCALE, + GLX_STATIC_COLOR, GLX_PSEUDO_COLOR, + GLX_TRUE_COLOR, GLX_DIRECT_COLOR + }; + + return ( (unsigned) visualType < NUM_VISUAL_TYPES ) + ? glx_visual_types[ visualType ] : GLX_NONE; +} + + +/**********************************************************************/ +/***** Public Functions *****/ +/**********************************************************************/ + + +/* + * Create a new X/Mesa visual. + * Input: display - X11 display + * visinfo - an XVisualInfo pointer + * rgb_flag - GL_TRUE = RGB mode, + * GL_FALSE = color index mode + * alpha_flag - alpha buffer requested? + * db_flag - GL_TRUE = double-buffered, + * GL_FALSE = single buffered + * stereo_flag - stereo visual? + * ximage_flag - GL_TRUE = use an XImage for back buffer, + * GL_FALSE = use an off-screen pixmap for back buffer + * depth_size - requested bits/depth values, or zero + * stencil_size - requested bits/stencil values, or zero + * accum_red_size - requested bits/red accum values, or zero + * accum_green_size - requested bits/green accum values, or zero + * accum_blue_size - requested bits/blue accum values, or zero + * accum_alpha_size - requested bits/alpha accum values, or zero + * num_samples - number of samples/pixel if multisampling, or zero + * level - visual level, usually 0 + * visualCaveat - ala the GLX extension, usually GLX_NONE + * Return; a new XMesaVisual or 0 if error. + */ +PUBLIC +XMesaVisual XMesaCreateVisual( Display *display, + XVisualInfo * visinfo, + GLboolean rgb_flag, + GLboolean alpha_flag, + GLboolean db_flag, + GLboolean stereo_flag, + GLboolean ximage_flag, + GLint depth_size, + GLint stencil_size, + GLint accum_red_size, + GLint accum_green_size, + GLint accum_blue_size, + GLint accum_alpha_size, + GLint num_samples, + GLint level, + GLint visualCaveat ) +{ + XMesaVisual v; + GLint red_bits, green_bits, blue_bits, alpha_bits; + + /* For debugging only */ + if (_mesa_getenv("MESA_XSYNC")) { + /* This makes debugging X easier. + * In your debugger, set a breakpoint on _XError to stop when an + * X protocol error is generated. + */ + XSynchronize( display, 1 ); + } + + v = (XMesaVisual) CALLOC_STRUCT(xmesa_visual); + if (!v) { + return NULL; + } + + v->display = display; + + /* Save a copy of the XVisualInfo struct because the user may X_mesa_free() + * the struct but we may need some of the information contained in it + * at a later time. + */ + v->visinfo = (XVisualInfo *) MALLOC(sizeof(*visinfo)); + if(!v->visinfo) { + _mesa_free(v); + return NULL; + } + MEMCPY(v->visinfo, visinfo, sizeof(*visinfo)); + + v->ximage_flag = ximage_flag; + + v->mesa_visual.redMask = visinfo->red_mask; + v->mesa_visual.greenMask = visinfo->green_mask; + v->mesa_visual.blueMask = visinfo->blue_mask; + v->mesa_visual.visualID = visinfo->visualid; + v->mesa_visual.screen = visinfo->screen; + +#if !(defined(__cplusplus) || defined(c_plusplus)) + v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->class); +#else + v->mesa_visual.visualType = xmesa_convert_from_x_visual_type(visinfo->c_class); +#endif + + v->mesa_visual.visualRating = visualCaveat; + + if (alpha_flag) + v->mesa_visual.alphaBits = 8; + + (void) initialize_visual_and_buffer( v, NULL, rgb_flag, 0, 0 ); + + { + const int xclass = v->mesa_visual.visualType; + if (xclass == GLX_TRUE_COLOR || xclass == GLX_DIRECT_COLOR) { + red_bits = _mesa_bitcount(GET_REDMASK(v)); + green_bits = _mesa_bitcount(GET_GREENMASK(v)); + blue_bits = _mesa_bitcount(GET_BLUEMASK(v)); + } + else { + /* this is an approximation */ + int depth; + depth = v->visinfo->depth; + red_bits = depth / 3; + depth -= red_bits; + green_bits = depth / 2; + depth -= green_bits; + blue_bits = depth; + alpha_bits = 0; + assert( red_bits + green_bits + blue_bits == v->visinfo->depth ); + } + alpha_bits = v->mesa_visual.alphaBits; + } + + _mesa_initialize_visual( &v->mesa_visual, + rgb_flag, db_flag, stereo_flag, + red_bits, green_bits, + blue_bits, alpha_bits, + v->mesa_visual.indexBits, + depth_size, + stencil_size, + accum_red_size, accum_green_size, + accum_blue_size, accum_alpha_size, + 0 ); + + /* XXX minor hack */ + v->mesa_visual.level = level; + return v; +} + + +PUBLIC +void XMesaDestroyVisual( XMesaVisual v ) +{ + _mesa_free(v->visinfo); + _mesa_free(v); +} + + + +/** + * Create a new XMesaContext. + * \param v the XMesaVisual + * \param share_list another XMesaContext with which to share display + * lists or NULL if no sharing is wanted. + * \return an XMesaContext or NULL if error. + */ +PUBLIC +XMesaContext XMesaCreateContext( XMesaVisual v, XMesaContext share_list ) +{ + static GLboolean firstTime = GL_TRUE; + struct pipe_screen *screen; + struct pipe_context *pipe; + XMesaContext c; + GLcontext *mesaCtx; + uint pf; + + if (firstTime) { + pipe_mutex_init(_xmesa_lock); + firstTime = GL_FALSE; + } + + /* Note: the XMesaContext contains a Mesa GLcontext struct (inheritance) */ + c = (XMesaContext) CALLOC_STRUCT(xmesa_context); + if (!c) + return NULL; + + pf = choose_pixel_format(v); + assert(pf); + + c->xm_visual = v; + c->xm_buffer = NULL; /* set later by XMesaMakeCurrent */ + + /* XXX: create once per Xlib Display. + */ + screen = driver.create_pipe_screen(); + if (screen == NULL) + goto fail; + + pipe = driver.create_pipe_context( screen, + (void *)c ); + if (pipe == NULL) + goto fail; + + c->st = st_create_context(pipe, + &v->mesa_visual, + share_list ? share_list->st : NULL); + if (c->st == NULL) + goto fail; + + mesaCtx = c->st->ctx; + c->st->ctx->DriverCtx = c; + +#if 00 + _mesa_enable_sw_extensions(mesaCtx); + _mesa_enable_1_3_extensions(mesaCtx); + _mesa_enable_1_4_extensions(mesaCtx); + _mesa_enable_1_5_extensions(mesaCtx); + _mesa_enable_2_0_extensions(mesaCtx); +#endif + + return c; + + fail: + if (c->st) + st_destroy_context(c->st); + else if (pipe) + pipe->destroy(pipe); + + if (screen) + screen->destroy( screen ); + + FREE(c); + return NULL; +} + + + +PUBLIC +void XMesaDestroyContext( XMesaContext c ) +{ + st_destroy_context(c->st); + + /* FIXME: We should destroy the screen here, but if we do so, surfaces may + * outlive it, causing segfaults + struct pipe_screen *screen = c->st->pipe->screen; + screen->destroy(screen); + */ + + _mesa_free(c); +} + + + +/** + * Private function for creating an XMesaBuffer which corresponds to an + * X window or pixmap. + * \param v the window's XMesaVisual + * \param w the window we're wrapping + * \return new XMesaBuffer or NULL if error + */ +PUBLIC XMesaBuffer +XMesaCreateWindowBuffer(XMesaVisual v, Window w) +{ + XWindowAttributes attr; + XMesaBuffer b; + Colormap cmap; + int depth; + + assert(v); + assert(w); + + /* Check that window depth matches visual depth */ + XGetWindowAttributes( v->display, w, &attr ); + depth = attr.depth; + if (v->visinfo->depth != depth) { + _mesa_warning(NULL, "XMesaCreateWindowBuffer: depth mismatch between visual (%d) and window (%d)!\n", + v->visinfo->depth, depth); + return NULL; + } + + /* Find colormap */ + if (attr.colormap) { + cmap = attr.colormap; + } + else { + _mesa_warning(NULL, "Window %u has no colormap!\n", (unsigned int) w); + /* this is weird, a window w/out a colormap!? */ + /* OK, let's just allocate a new one and hope for the best */ + cmap = XCreateColormap(v->display, w, attr.visual, AllocNone); + } + + b = create_xmesa_buffer((Drawable) w, WINDOW, v, cmap); + if (!b) + return NULL; + + if (!initialize_visual_and_buffer( v, b, v->mesa_visual.rgbMode, + (Drawable) w, cmap )) { + xmesa_free_buffer(b); + return NULL; + } + + return b; +} + + + +/** + * Create a new XMesaBuffer from an X pixmap. + * + * \param v the XMesaVisual + * \param p the pixmap + * \param cmap the colormap, may be 0 if using a \c GLX_TRUE_COLOR or + * \c GLX_DIRECT_COLOR visual for the pixmap + * \returns new XMesaBuffer or NULL if error + */ +PUBLIC XMesaBuffer +XMesaCreatePixmapBuffer(XMesaVisual v, Pixmap p, Colormap cmap) +{ + XMesaBuffer b; + + assert(v); + + b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); + if (!b) + return NULL; + + if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, + (Drawable) p, cmap)) { + xmesa_free_buffer(b); + return NULL; + } + + return b; +} + + +/** + * For GLX_EXT_texture_from_pixmap + */ +XMesaBuffer +XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, + Colormap cmap, + int format, int target, int mipmap) +{ + GET_CURRENT_CONTEXT(ctx); + XMesaBuffer b; + GLuint width, height; + + assert(v); + + b = create_xmesa_buffer((Drawable) p, PIXMAP, v, cmap); + if (!b) + return NULL; + + /* get pixmap size, update framebuffer/renderbuffer dims */ + xmesa_get_window_size(v->display, b, &width, &height); + _mesa_resize_framebuffer(NULL, &(b->stfb->Base), width, height); + + if (target == 0) { + /* examine dims */ + if (ctx->Extensions.ARB_texture_non_power_of_two) { + target = GLX_TEXTURE_2D_EXT; + } + else if ( _mesa_bitcount(width) == 1 + && _mesa_bitcount(height) == 1) { + /* power of two size */ + if (height == 1) { + target = GLX_TEXTURE_1D_EXT; + } + else { + target = GLX_TEXTURE_2D_EXT; + } + } + else if (ctx->Extensions.NV_texture_rectangle) { + target = GLX_TEXTURE_RECTANGLE_EXT; + } + else { + /* non power of two textures not supported */ + XMesaDestroyBuffer(b); + return 0; + } + } + + b->TextureTarget = target; + b->TextureFormat = format; + b->TextureMipmap = mipmap; + + if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, + (Drawable) p, cmap)) { + xmesa_free_buffer(b); + return NULL; + } + + return b; +} + + + +XMesaBuffer +XMesaCreatePBuffer(XMesaVisual v, Colormap cmap, + unsigned int width, unsigned int height) +{ + Window root; + Drawable drawable; /* X Pixmap Drawable */ + XMesaBuffer b; + + /* allocate pixmap for front buffer */ + root = RootWindow( v->display, v->visinfo->screen ); + drawable = XCreatePixmap(v->display, root, width, height, + v->visinfo->depth); + if (!drawable) + return NULL; + + b = create_xmesa_buffer(drawable, PBUFFER, v, cmap); + if (!b) + return NULL; + + if (!initialize_visual_and_buffer(v, b, v->mesa_visual.rgbMode, + drawable, cmap)) { + xmesa_free_buffer(b); + return NULL; + } + + return b; +} + + + +/* + * Deallocate an XMesaBuffer structure and all related info. + */ +PUBLIC void +XMesaDestroyBuffer(XMesaBuffer b) +{ + xmesa_free_buffer(b); +} + + +/** + * Query the current window size and update the corresponding GLframebuffer + * and all attached renderbuffers. + * Called when: + * 1. the first time a buffer is bound to a context. + * 2. SwapBuffers. XXX probabaly from xm_flush_frontbuffer() too... + * Note: it's possible (and legal) for xmctx to be NULL. That can happen + * when resizing a buffer when no rendering context is bound. + */ +void +xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer) +{ + GLuint width, height; + xmesa_get_window_size(drawBuffer->xm_visual->display, drawBuffer, &width, &height); + st_resize_framebuffer(drawBuffer->stfb, width, height); +} + + + + +/* + * Bind buffer b to context c and make c the current rendering context. + */ +PUBLIC +GLboolean XMesaMakeCurrent2( XMesaContext c, XMesaBuffer drawBuffer, + XMesaBuffer readBuffer ) +{ + if (c) { + if (!drawBuffer || !readBuffer) + return GL_FALSE; /* must specify buffers! */ + +#if 0 + /* XXX restore this optimization */ + if (&(c->mesa) == _mesa_get_current_context() + && c->mesa.DrawBuffer == &drawBuffer->mesa_buffer + && c->mesa.ReadBuffer == &readBuffer->mesa_buffer + && xmesa_buffer(c->mesa.DrawBuffer)->wasCurrent) { + /* same context and buffer, do nothing */ + return GL_TRUE; + } +#endif + + c->xm_buffer = drawBuffer; + + /* Call this periodically to detect when the user has begun using + * GL rendering from multiple threads. + */ + _glapi_check_multithread(); + + st_make_current(c->st, drawBuffer->stfb, readBuffer->stfb); + + xmesa_check_and_update_buffer_size(c, drawBuffer); + if (readBuffer != drawBuffer) + xmesa_check_and_update_buffer_size(c, readBuffer); + + /* Solution to Stephane Rehel's problem with glXReleaseBuffersMESA(): */ + drawBuffer->wasCurrent = GL_TRUE; + } + else { + /* Detach */ + st_make_current( NULL, NULL, NULL ); + } + return GL_TRUE; +} + + +/* + * Unbind the context c from its buffer. + */ +GLboolean XMesaUnbindContext( XMesaContext c ) +{ + /* A no-op for XFree86 integration purposes */ + return GL_TRUE; +} + + +XMesaContext XMesaGetCurrentContext( void ) +{ + GET_CURRENT_CONTEXT(ctx); + if (ctx) { + XMesaContext xmesa = xmesa_context(ctx); + return xmesa; + } + else { + return 0; + } +} + + + + + + +/* + * Copy the back buffer to the front buffer. If there's no back buffer + * this is a no-op. + */ +PUBLIC +void XMesaSwapBuffers( XMesaBuffer b ) +{ + struct pipe_surface *surf; + + /* If we're swapping the buffer associated with the current context + * we have to flush any pending rendering commands first. + */ + st_notify_swapbuffers(b->stfb); + + st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf); + if (surf) { + driver.display_surface(b, surf); + } + + xmesa_check_and_update_buffer_size(NULL, b); +} + + + +/* + * Copy sub-region of back buffer to front buffer + */ +void XMesaCopySubBuffer( XMesaBuffer b, int x, int y, int width, int height ) +{ + struct pipe_surface *surf_front; + struct pipe_surface *surf_back; + struct pipe_context *pipe = NULL; /* XXX fix */ + + st_get_framebuffer_surface(b->stfb, ST_SURFACE_FRONT_LEFT, &surf_front); + st_get_framebuffer_surface(b->stfb, ST_SURFACE_BACK_LEFT, &surf_back); + + if (!surf_front || !surf_back) + return; + + pipe->surface_copy(pipe, + FALSE, + surf_front, x, y, /* dest */ + surf_back, x, y, /* src */ + width, height); +} + + + +void XMesaFlush( XMesaContext c ) +{ + if (c && c->xm_visual->display) { + st_finish(c->st); + XSync( c->xm_visual->display, False ); + } +} + + + + + +XMesaBuffer XMesaFindBuffer( Display *dpy, Drawable d ) +{ + XMesaBuffer b; + for (b=XMesaBufferList; b; b=b->Next) { + if (b->drawable == d && b->xm_visual->display == dpy) { + return b; + } + } + return NULL; +} + + +/** + * Free/destroy all XMesaBuffers associated with given display. + */ +void xmesa_destroy_buffers_on_display(Display *dpy) +{ + XMesaBuffer b, next; + for (b = XMesaBufferList; b; b = next) { + next = b->Next; + if (b->xm_visual->display == dpy) { + xmesa_free_buffer(b); + } + } +} + + +/* + * Look for XMesaBuffers whose X window has been destroyed. + * Deallocate any such XMesaBuffers. + */ +void XMesaGarbageCollect( void ) +{ + XMesaBuffer b, next; + for (b=XMesaBufferList; b; b=next) { + next = b->Next; + if (b->xm_visual && + b->xm_visual->display && + b->drawable && + b->type == WINDOW) { + XSync(b->xm_visual->display, False); + if (!window_exists( b->xm_visual->display, b->drawable )) { + /* found a dead window, free the ancillary info */ + XMesaDestroyBuffer( b ); + } + } + } +} + + + + +PUBLIC void +XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, + const int *attrib_list) +{ +} + + + +PUBLIC void +XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer) +{ +} + diff --git a/src/gallium/state_trackers/glx/xlib/xm_api.h b/src/gallium/state_trackers/glx/xlib/xm_api.h new file mode 100644 index 00000000000..2b8302d1747 --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_api.h @@ -0,0 +1,393 @@ +/* + * Mesa 3-D graphics library + * Version: 7.1 + * + * Copyright (C) 1999-2007 Brian Paul All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the "Software"), + * to deal in the Software without restriction, including without limitation + * the rights to use, copy, modify, merge, publish, distribute, sublicense, + * and/or sell copies of the Software, and to permit persons to whom the + * Software is furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included + * in all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL + * BRIAN PAUL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN + * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN + * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + */ + + + +/* Sample Usage: + +In addition to the usual X calls to select a visual, create a colormap +and create a window, you must do the following to use the X/Mesa interface: + +1. Call XMesaCreateVisual() to make an XMesaVisual from an XVisualInfo. + +2. Call XMesaCreateContext() to create an X/Mesa rendering context, given + the XMesaVisual. + +3. Call XMesaCreateWindowBuffer() to create an XMesaBuffer from an X window + and XMesaVisual. + +4. Call XMesaMakeCurrent() to bind the XMesaBuffer to an XMesaContext and + to make the context the current one. + +5. Make gl* calls to render your graphics. + +6. Use XMesaSwapBuffers() when double buffering to swap front/back buffers. + +7. Before the X window is destroyed, call XMesaDestroyBuffer(). + +8. Before exiting, call XMesaDestroyVisual and XMesaDestroyContext. + +*/ + + + + +#ifndef XMESA_H +#define XMESA_H + + +#include "mtypes.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_public.h" +#include "pipe/p_thread.h" + + +# include <X11/Xlib.h> +# include <X11/Xlibint.h> +# include <X11/Xutil.h> +# ifdef USE_XSHM /* was SHM */ +# include <sys/ipc.h> +# include <sys/shm.h> +# include <X11/extensions/XShm.h> +# endif + +typedef struct xmesa_buffer *XMesaBuffer; +typedef struct xmesa_context *XMesaContext; +typedef struct xmesa_visual *XMesaVisual; + + + +/* + * Create a new X/Mesa visual. + * Input: display - X11 display + * visinfo - an XVisualInfo pointer + * rgb_flag - GL_TRUE = RGB mode, + * GL_FALSE = color index mode + * alpha_flag - alpha buffer requested? + * db_flag - GL_TRUE = double-buffered, + * GL_FALSE = single buffered + * stereo_flag - stereo visual? + * ximage_flag - GL_TRUE = use an XImage for back buffer, + * GL_FALSE = use an off-screen pixmap for back buffer + * depth_size - requested bits/depth values, or zero + * stencil_size - requested bits/stencil values, or zero + * accum_red_size - requested bits/red accum values, or zero + * accum_green_size - requested bits/green accum values, or zero + * accum_blue_size - requested bits/blue accum values, or zero + * accum_alpha_size - requested bits/alpha accum values, or zero + * num_samples - number of samples/pixel if multisampling, or zero + * level - visual level, usually 0 + * visualCaveat - ala the GLX extension, usually GLX_NONE_EXT + * Return; a new XMesaVisual or 0 if error. + */ +extern XMesaVisual XMesaCreateVisual( Display *display, + XVisualInfo * visinfo, + GLboolean rgb_flag, + GLboolean alpha_flag, + GLboolean db_flag, + GLboolean stereo_flag, + GLboolean ximage_flag, + GLint depth_size, + GLint stencil_size, + GLint accum_red_size, + GLint accum_green_size, + GLint accum_blue_size, + GLint accum_alpha_size, + GLint num_samples, + GLint level, + GLint visualCaveat ); + +/* + * Destroy an XMesaVisual, but not the associated XVisualInfo. + */ +extern void XMesaDestroyVisual( XMesaVisual v ); + + + +/* + * Create a new XMesaContext for rendering into an X11 window. + * + * Input: visual - an XMesaVisual + * share_list - another XMesaContext with which to share display + * lists or NULL if no sharing is wanted. + * Return: an XMesaContext or NULL if error. + */ +extern XMesaContext XMesaCreateContext( XMesaVisual v, + XMesaContext share_list ); + + +/* + * Destroy a rendering context as returned by XMesaCreateContext() + */ +extern void XMesaDestroyContext( XMesaContext c ); + + + +/* + * Create an XMesaBuffer from an X window. + */ +extern XMesaBuffer XMesaCreateWindowBuffer( XMesaVisual v, Window w ); + + +/* + * Create an XMesaBuffer from an X pixmap. + */ +extern XMesaBuffer XMesaCreatePixmapBuffer( XMesaVisual v, + Pixmap p, + Colormap cmap ); + + +/* + * Destroy an XMesaBuffer, but not the corresponding window or pixmap. + */ +extern void XMesaDestroyBuffer( XMesaBuffer b ); + + +/* + * Return the XMesaBuffer handle which corresponds to an X drawable, if any. + * + * New in Mesa 2.3. + */ +extern XMesaBuffer XMesaFindBuffer( Display *dpy, + Drawable d ); + + + +/* + * Bind two buffers (read and draw) to a context and make the + * context the current one. + * New in Mesa 3.3 + */ +extern GLboolean XMesaMakeCurrent2( XMesaContext c, + XMesaBuffer drawBuffer, + XMesaBuffer readBuffer ); + + +/* + * Unbind the current context from its buffer. + */ +extern GLboolean XMesaUnbindContext( XMesaContext c ); + + +/* + * Return a handle to the current context. + */ +extern XMesaContext XMesaGetCurrentContext( void ); + + +/* + * Swap the front and back buffers for the given buffer. No action is + * taken if the buffer is not double buffered. + */ +extern void XMesaSwapBuffers( XMesaBuffer b ); + + +/* + * Copy a sub-region of the back buffer to the front buffer. + * + * New in Mesa 2.6 + */ +extern void XMesaCopySubBuffer( XMesaBuffer b, + int x, + int y, + int width, + int height ); + + + + + +/* + * Flush/sync a context + */ +extern void XMesaFlush( XMesaContext c ); + + + +/* + * Scan for XMesaBuffers whose window/pixmap has been destroyed, then free + * any memory used by that buffer. + * + * New in Mesa 2.3. + */ +extern void XMesaGarbageCollect( void ); + + + +/* + * Create a pbuffer. + * New in Mesa 4.1 + */ +extern XMesaBuffer XMesaCreatePBuffer(XMesaVisual v, Colormap cmap, + unsigned int width, unsigned int height); + + + +/* + * Texture from Pixmap + * New in Mesa 7.1 + */ +extern void +XMesaBindTexImage(Display *dpy, XMesaBuffer drawable, int buffer, + const int *attrib_list); + +extern void +XMesaReleaseTexImage(Display *dpy, XMesaBuffer drawable, int buffer); + + +extern XMesaBuffer +XMesaCreatePixmapTextureBuffer(XMesaVisual v, Pixmap p, + Colormap cmap, + int format, int target, int mipmap); + + + + +/*********************************************************************** + */ + +extern pipe_mutex _xmesa_lock; + +extern struct xmesa_buffer *XMesaBufferList; + + +/** + * Visual inforation, derived from GLvisual. + * Basically corresponds to an XVisualInfo. + */ +struct xmesa_visual { + GLvisual mesa_visual; /* Device independent visual parameters */ + Display *display; /* The X11 display */ + XVisualInfo * visinfo; /* X's visual info (pointer to private copy) */ + XVisualInfo *vishandle; /* Only used in fakeglx.c */ + GLint BitsPerPixel; /* True bits per pixel for XImages */ + + GLboolean ximage_flag; /* Use XImage for back buffer (not pixmap)? */ +}; + + +/** + * Context info, derived from st_context. + * Basically corresponds to a GLXContext. + */ +struct xmesa_context { + struct st_context *st; + XMesaVisual xm_visual; /** pixel format info */ + XMesaBuffer xm_buffer; /** current drawbuffer */ +}; + + +/** + * Types of X/GLX drawables we might render into. + */ +typedef enum { + WINDOW, /* An X window */ + GLXWINDOW, /* GLX window */ + PIXMAP, /* GLX pixmap */ + PBUFFER /* GLX Pbuffer */ +} BufferType; + + +/** + * Framebuffer information, derived from. + * Basically corresponds to a GLXDrawable. + */ +struct xmesa_buffer { + struct st_framebuffer *stfb; + + GLboolean wasCurrent; /* was ever the current buffer? */ + XMesaVisual xm_visual; /* the X/Mesa visual */ + Drawable drawable; /* Usually the X window ID */ + Colormap cmap; /* the X colormap */ + BufferType type; /* window, pixmap, pbuffer or glxwindow */ + + XImage *tempImage; + unsigned long selectedEvents;/* for pbuffers only */ + + GLuint shm; /* X Shared Memory extension status: */ + /* 0 = not available */ + /* 1 = XImage support available */ + /* 2 = Pixmap support available too */ +#if defined(USE_XSHM) + XShmSegmentInfo shminfo; +#endif + + GC gc; /* scratch GC for span, line, tri drawing */ + + /* GLX_EXT_texture_from_pixmap */ + GLint TextureTarget; /** GLX_TEXTURE_1D_EXT, for example */ + GLint TextureFormat; /** GLX_TEXTURE_FORMAT_RGB_EXT, for example */ + GLint TextureMipmap; /** 0 or 1 */ + + struct xmesa_buffer *Next; /* Linked list pointer: */ +}; + + + +/** cast wrapper */ +static INLINE XMesaContext +xmesa_context(GLcontext *ctx) +{ + return (XMesaContext) ctx->DriverCtx; +} + + +/** cast wrapper */ +static INLINE XMesaBuffer +xmesa_buffer(GLframebuffer *fb) +{ + struct st_framebuffer *stfb = (struct st_framebuffer *) fb; + return (XMesaBuffer) st_framebuffer_private(stfb); +} + + +extern void +xmesa_delete_framebuffer(struct gl_framebuffer *fb); + +extern XMesaBuffer +xmesa_find_buffer(Display *dpy, Colormap cmap, XMesaBuffer notThis); + +extern void +xmesa_check_and_update_buffer_size(XMesaContext xmctx, XMesaBuffer drawBuffer); + +extern void +xmesa_destroy_buffers_on_display(Display *dpy); + +static INLINE GLuint +xmesa_buffer_width(XMesaBuffer b) +{ + return b->stfb->Base.Width; +} + +static INLINE GLuint +xmesa_buffer_height(XMesaBuffer b) +{ + return b->stfb->Base.Height; +} + +extern int +xmesa_check_for_xshm(Display *display); + + +#endif diff --git a/src/gallium/state_trackers/glx/xlib/xm_winsys.h b/src/gallium/state_trackers/glx/xlib/xm_winsys.h new file mode 100644 index 00000000000..0e57605c34b --- /dev/null +++ b/src/gallium/state_trackers/glx/xlib/xm_winsys.h @@ -0,0 +1,59 @@ + +/************************************************************************** + * + * Copyright 2006 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef XM_WINSYS_H +#define XM_WINSYS_H + +struct pipe_context; +struct pipe_screen; +struct pipe_surface; +struct xmesa_buffer; + + +struct xm_driver { + + struct pipe_screen *(*create_pipe_screen)( void ); + + /* The context_private argument needs to go away. Is currently used + * in a round-about way to associate a display-target surface with its + * Xlib window. + */ + struct pipe_context *(*create_pipe_context)( struct pipe_screen *, + void *context_private ); + + void (*display_surface)( struct xmesa_buffer *, + struct pipe_surface * ); + +}; + + +extern void +xmesa_set_driver( const struct xm_driver *driver ); + + +#endif diff --git a/src/gallium/state_trackers/python/README b/src/gallium/state_trackers/python/README new file mode 100644 index 00000000000..8f45fb6d1b7 --- /dev/null +++ b/src/gallium/state_trackers/python/README @@ -0,0 +1,33 @@ +This directory contains Python bindings to Gallium3D. It looks like a state +tracker from the pipe driver perspective, and it looks like a pipe driver from +the python script perspective. + + +To build you'll need: +* Python (with development packages) +* SCons +* SWIG +* Python Imaging Library with TK support (for the samples) + +Invoke scons on the top dir as + + scons statetrackers=python + +To use do + + export PYTHONPATH=build/XXXX-XXXX-XXXX/gallium/state_trackers/python + +and then try running + + python src/gallium/state_trackers/python/samples/tri.py + +which should show a triangle. + + +This is still work in progress: +- errors are not handled properly and almost always result in crash +- state atoms with array members are awkward to set +- there no efficient way to view images + +-- +Jose Fonseca <[email protected]> diff --git a/src/gallium/state_trackers/python/SConscript b/src/gallium/state_trackers/python/SConscript new file mode 100644 index 00000000000..1581182aec2 --- /dev/null +++ b/src/gallium/state_trackers/python/SConscript @@ -0,0 +1,34 @@ +import sys +import os.path + +Import('*') + +if 'python' in env['statetrackers']: + + env = env.Clone() + + env.Tool('python') + + env.Tool('swig') + env.Append(SWIGPATH = ['#src/gallium/include', '#src/gallium/include/pipe']) + env.Append(SWIGFLAGS = ['-python', '-keyword']) + + env.Append(CPPPATH = '.') + + pyst = env.ConvenienceLibrary( + target = 'pyst', + source = [ + 'gallium.i', + 'st_device.c', + 'st_sample.c', + 'st_softpipe_winsys.c', + ], + ) + + env.SharedLibrary( + target = '_gallium', + source = [ + 'st_hardpipe_winsys.c', + ], + LIBS = [pyst, softpipe, trace] + auxiliaries + env['LIBS'], + ) diff --git a/src/gallium/state_trackers/python/gallium.i b/src/gallium/state_trackers/python/gallium.i new file mode 100644 index 00000000000..f4c4b36ea7d --- /dev/null +++ b/src/gallium/state_trackers/python/gallium.i @@ -0,0 +1,103 @@ + /************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * SWIG interface definion for Gallium types. + * + * @author Jose Fonseca <[email protected]> + */ + +%module gallium; + +%{ + +#include <stdio.h> +#include <Python.h> + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_inlines.h" +#include "util/u_memory.h" +#include "pipe/p_shader_tokens.h" +#include "cso_cache/cso_context.h" +#include "util/u_draw_quad.h" +#include "util/u_tile.h" +#include "tgsi/tgsi_text.h" +#include "tgsi/tgsi_dump.h" + +#include "st_device.h" +#include "st_sample.h" + +%} + +%include "typemaps.i" + +%include "cstring.i" + +%include "carrays.i" +%array_class(unsigned char, ByteArray); +%array_class(int, IntArray); +%array_class(unsigned, UnsignedArray); +%array_class(float, FloatArray); + + +%rename(Device) st_device; +%rename(Context) st_context; +%rename(Texture) pipe_texture; +%rename(Surface) pipe_surface; +%rename(Buffer) st_buffer; + +%rename(BlendColor) pipe_blend_color; +%rename(Blend) pipe_blend_state; +%rename(Clip) pipe_clip_state; +%rename(ConstantBuffer) pipe_constant_buffer; +%rename(Depth) pipe_depth_state; +%rename(Stencil) pipe_stencil_state; +%rename(Alpha) pipe_alpha_state; +%rename(DepthStencilAlpha) pipe_depth_stencil_alpha_state; +%rename(FormatBlock) pipe_format_block; +%rename(Framebuffer) pipe_framebuffer_state; +%rename(PolyStipple) pipe_poly_stipple; +%rename(Rasterizer) pipe_rasterizer_state; +%rename(Sampler) pipe_sampler_state; +%rename(Scissor) pipe_scissor_state; +%rename(Shader) pipe_shader_state; +%rename(VertexBuffer) pipe_vertex_buffer; +%rename(VertexElement) pipe_vertex_element; +%rename(Viewport) pipe_viewport_state; + + +%include "p_compiler.i" +%include "pipe/p_defines.h"; +%include "p_format.i" + +%include "p_device.i" +%include "p_context.i" +%include "p_texture.i" +%include "p_state.i" + diff --git a/src/gallium/state_trackers/python/p_compiler.i b/src/gallium/state_trackers/python/p_compiler.i new file mode 100644 index 00000000000..15f6ba5b9db --- /dev/null +++ b/src/gallium/state_trackers/python/p_compiler.i @@ -0,0 +1,29 @@ + /************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +typedef unsigned char ubyte; diff --git a/src/gallium/state_trackers/python/p_context.i b/src/gallium/state_trackers/python/p_context.i new file mode 100644 index 00000000000..7b8b64b5923 --- /dev/null +++ b/src/gallium/state_trackers/python/p_context.i @@ -0,0 +1,289 @@ + /************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * SWIG interface definion for Gallium types. + * + * @author Jose Fonseca <[email protected]> + */ + +%nodefaultctor st_context; +%nodefaultdtor st_context; + +struct st_context { +}; + +%extend st_context { + + ~st_context() { + st_context_destroy($self); + } + + /* + * State functions (create/bind/destroy state objects) + */ + + void set_blend( const struct pipe_blend_state *state ) { + cso_set_blend($self->cso, state); + } + + void set_sampler( unsigned index, const struct pipe_sampler_state *state ) { + cso_single_sampler($self->cso, index, state); + cso_single_sampler_done($self->cso); + } + + void set_rasterizer( const struct pipe_rasterizer_state *state ) { + cso_set_rasterizer($self->cso, state); + } + + void set_depth_stencil_alpha(const struct pipe_depth_stencil_alpha_state *state) { + cso_set_depth_stencil_alpha($self->cso, state); + } + + void set_fragment_shader( const struct pipe_shader_state *state ) { + void *fs; + + if(!state) { + cso_set_fragment_shader_handle($self->cso, NULL); + return; + } + + fs = $self->pipe->create_fs_state($self->pipe, state); + if(!fs) + return; + + if(cso_set_fragment_shader_handle($self->cso, fs) != PIPE_OK) + return; + + cso_delete_fragment_shader($self->cso, $self->fs); + $self->fs = fs; + } + + void set_vertex_shader( const struct pipe_shader_state *state ) { + void *vs; + + if(!state) { + cso_set_vertex_shader_handle($self->cso, NULL); + return; + } + + vs = $self->pipe->create_vs_state($self->pipe, state); + if(!vs) + return; + + if(cso_set_vertex_shader_handle($self->cso, vs) != PIPE_OK) + return; + + cso_delete_vertex_shader($self->cso, $self->vs); + $self->vs = vs; + } + + /* + * Parameter-like state (or properties) + */ + + void set_blend_color(const struct pipe_blend_color *state ) { + cso_set_blend_color($self->cso, state); + } + + void set_clip(const struct pipe_clip_state *state ) { + $self->pipe->set_clip_state($self->pipe, state); + } + + void set_constant_buffer(unsigned shader, unsigned index, + struct st_buffer *buffer ) + { + struct pipe_constant_buffer state; + memset(&state, 0, sizeof(state)); + state.buffer = buffer ? buffer->buffer : NULL; + state.size = buffer->buffer->size; + $self->pipe->set_constant_buffer($self->pipe, shader, index, &state); + } + + void set_framebuffer(const struct pipe_framebuffer_state *state ) { + cso_set_framebuffer($self->cso, state); + } + + void set_polygon_stipple(const struct pipe_poly_stipple *state ) { + $self->pipe->set_polygon_stipple($self->pipe, state); + } + + void set_scissor(const struct pipe_scissor_state *state ) { + $self->pipe->set_scissor_state($self->pipe, state); + } + + void set_viewport(const struct pipe_viewport_state *state) { + cso_set_viewport($self->cso, state); + } + + void set_sampler_texture(unsigned index, + struct pipe_texture *texture) { + if(!texture) + texture = $self->default_texture; + pipe_texture_reference(&$self->sampler_textures[index], texture); + $self->pipe->set_sampler_textures($self->pipe, + PIPE_MAX_SAMPLERS, + $self->sampler_textures); + } + + void set_vertex_buffer(unsigned index, + unsigned pitch, + unsigned max_index, + unsigned buffer_offset, + struct st_buffer *buffer) + { + unsigned i; + struct pipe_vertex_buffer state; + + memset(&state, 0, sizeof(state)); + state.pitch = pitch; + state.max_index = max_index; + state.buffer_offset = buffer_offset; + state.buffer = buffer ? buffer->buffer : NULL; + + memcpy(&$self->vertex_buffers[index], &state, sizeof(state)); + + for(i = 0; i < PIPE_MAX_ATTRIBS; ++i) + if(self->vertex_buffers[i].buffer) + $self->num_vertex_buffers = i + 1; + + $self->pipe->set_vertex_buffers($self->pipe, + $self->num_vertex_buffers, + $self->vertex_buffers); + } + + void set_vertex_element(unsigned index, + const struct pipe_vertex_element *element) + { + memcpy(&$self->vertex_elements[index], element, sizeof(*element)); + } + + void set_vertex_elements(unsigned num) + { + $self->num_vertex_elements = num; + $self->pipe->set_vertex_elements($self->pipe, + $self->num_vertex_elements, + $self->vertex_elements); + } + + /* + * Draw functions + */ + + void draw_arrays(unsigned mode, unsigned start, unsigned count) { + $self->pipe->draw_arrays($self->pipe, mode, start, count); + } + + void draw_elements( struct st_buffer *indexBuffer, + unsigned indexSize, + unsigned mode, unsigned start, unsigned count) + { + $self->pipe->draw_elements($self->pipe, + indexBuffer->buffer, + indexSize, + mode, start, count); + } + + void draw_range_elements( struct st_buffer *indexBuffer, + unsigned indexSize, unsigned minIndex, unsigned maxIndex, + unsigned mode, unsigned start, unsigned count) + { + $self->pipe->draw_range_elements($self->pipe, + indexBuffer->buffer, + indexSize, minIndex, maxIndex, + mode, start, count); + } + + void draw_vertices(unsigned prim, + unsigned num_verts, + unsigned num_attribs, + const float *vertices) + { + struct pipe_context *pipe = $self->pipe; + struct pipe_screen *screen = pipe->screen; + struct pipe_buffer *vbuf; + float *map; + unsigned size; + + size = num_verts * num_attribs * 4 * sizeof(float); + + vbuf = pipe_buffer_create(screen, + 32, + PIPE_BUFFER_USAGE_VERTEX, + size); + if(!vbuf) + goto error1; + + map = pipe_buffer_map(screen, vbuf, PIPE_BUFFER_USAGE_CPU_WRITE); + if (!map) + goto error2; + memcpy(map, vertices, size); + pipe_buffer_unmap(screen, vbuf); + + util_draw_vertex_buffer(pipe, vbuf, 0, prim, num_verts, num_attribs); + +error2: + pipe_buffer_reference(screen, &vbuf, NULL); +error1: + ; + } + + void + flush(unsigned flags = 0) { + struct pipe_fence_handle *fence = NULL; + $self->pipe->flush($self->pipe, flags | PIPE_FLUSH_RENDER_CACHE, &fence); + /* TODO: allow asynchronous operation */ + $self->pipe->winsys->fence_finish( $self->pipe->winsys, fence, 0 ); + $self->pipe->winsys->fence_reference( $self->pipe->winsys, &fence, NULL ); + } + + /* + * Surface functions + */ + + void surface_copy(int do_flip, + struct pipe_surface *dest, + unsigned destx, unsigned desty, + struct pipe_surface *src, + unsigned srcx, unsigned srcy, + unsigned width, unsigned height) { + $self->pipe->surface_copy($self->pipe, do_flip, dest, destx, desty, src, srcx, srcy, width, height); + } + + void surface_fill(struct pipe_surface *dst, + unsigned x, unsigned y, + unsigned width, unsigned height, + unsigned value) { + $self->pipe->surface_fill($self->pipe, dst, x, y, width, height, value); + } + + void surface_clear(struct pipe_surface *surface, unsigned value = 0) { + $self->pipe->clear($self->pipe, surface, value); + } + +}; diff --git a/src/gallium/state_trackers/python/p_device.i b/src/gallium/state_trackers/python/p_device.i new file mode 100644 index 00000000000..84fd2e4349b --- /dev/null +++ b/src/gallium/state_trackers/python/p_device.i @@ -0,0 +1,130 @@ + /************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * SWIG interface definion for Gallium types. + * + * @author Jose Fonseca <[email protected]> + */ + + +%nodefaultctor st_device; +%nodefaultdtor st_device; + + +struct st_device { +}; + +%newobject st_device::texture_create; +%newobject st_device::context_create; +%newobject st_device::buffer_create; + +%extend st_device { + + st_device(int hardware = 1) { + return st_device_create(hardware ? TRUE : FALSE); + } + + ~st_device() { + st_device_destroy($self); + } + + const char * get_name( void ) { + return $self->screen->get_name($self->screen); + } + + const char * get_vendor( void ) { + return $self->screen->get_vendor($self->screen); + } + + /** + * Query an integer-valued capability/parameter/limit + * \param param one of PIPE_CAP_x + */ + int get_param( int param ) { + return $self->screen->get_param($self->screen, param); + } + + /** + * Query a float-valued capability/parameter/limit + * \param param one of PIPE_CAP_x + */ + float get_paramf( int param ) { + return $self->screen->get_paramf($self->screen, param); + } + + /** + * Check if the given pipe_format is supported as a texture or + * drawing surface. + * \param type one of PIPE_TEXTURE, PIPE_SURFACE + */ + int is_format_supported( enum pipe_format format, + enum pipe_texture_target target, + unsigned tex_usage, + unsigned geom_flags ) { + return $self->screen->is_format_supported( $self->screen, + format, + target, + tex_usage, + geom_flags ); + } + + struct st_context * + context_create(void) { + return st_context_create($self); + } + + struct pipe_texture * + texture_create( + enum pipe_format format, + unsigned width, + unsigned height, + unsigned depth = 1, + unsigned last_level = 0, + enum pipe_texture_target target = PIPE_TEXTURE_2D, + unsigned tex_usage = 0 + ) { + struct pipe_texture templat; + memset(&templat, 0, sizeof(templat)); + templat.format = format; + pf_get_block(templat.format, &templat.block); + templat.width[0] = width; + templat.height[0] = height; + templat.depth[0] = depth; + templat.last_level = last_level; + templat.target = target; + templat.tex_usage = tex_usage; + return $self->screen->texture_create($self->screen, &templat); + } + + struct st_buffer * + buffer_create(unsigned size, unsigned alignment = 0, unsigned usage = 0) { + return st_buffer_create($self, alignment, usage, size); + } + +}; diff --git a/src/gallium/state_trackers/python/p_format.i b/src/gallium/state_trackers/python/p_format.i new file mode 100644 index 00000000000..26fb12b387f --- /dev/null +++ b/src/gallium/state_trackers/python/p_format.i @@ -0,0 +1,162 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * Copyright (c) 2008 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/* + * XXX: SWIG can't parse p_format.h, so we need to duplicate the relevant + * declarations here + */ + +%{ +#include "pipe/p_format.h" +%} + +enum pipe_format { + PIPE_FORMAT_NONE, + PIPE_FORMAT_A8R8G8B8_UNORM, + PIPE_FORMAT_X8R8G8B8_UNORM, + PIPE_FORMAT_B8G8R8A8_UNORM, + PIPE_FORMAT_B8G8R8X8_UNORM, + PIPE_FORMAT_A1R5G5B5_UNORM, + PIPE_FORMAT_A4R4G4B4_UNORM, + PIPE_FORMAT_R5G6B5_UNORM, + PIPE_FORMAT_A2B10G10R10_UNORM, + PIPE_FORMAT_L8_UNORM, + PIPE_FORMAT_A8_UNORM, + PIPE_FORMAT_I8_UNORM, + PIPE_FORMAT_A8L8_UNORM, + PIPE_FORMAT_L16_UNORM, + PIPE_FORMAT_YCBCR, + PIPE_FORMAT_YCBCR_REV, + PIPE_FORMAT_Z16_UNORM, + PIPE_FORMAT_Z32_UNORM, + PIPE_FORMAT_Z32_FLOAT, + PIPE_FORMAT_S8Z24_UNORM, + PIPE_FORMAT_Z24S8_UNORM, + PIPE_FORMAT_X8Z24_UNORM, + PIPE_FORMAT_Z24X8_UNORM, + PIPE_FORMAT_S8_UNORM, + PIPE_FORMAT_R64_FLOAT, + PIPE_FORMAT_R64G64_FLOAT, + PIPE_FORMAT_R64G64B64_FLOAT, + PIPE_FORMAT_R64G64B64A64_FLOAT, + PIPE_FORMAT_R32_FLOAT, + PIPE_FORMAT_R32G32_FLOAT, + PIPE_FORMAT_R32G32B32_FLOAT, + PIPE_FORMAT_R32G32B32A32_FLOAT, + PIPE_FORMAT_R32_UNORM, + PIPE_FORMAT_R32G32_UNORM, + PIPE_FORMAT_R32G32B32_UNORM, + PIPE_FORMAT_R32G32B32A32_UNORM, + PIPE_FORMAT_R32_USCALED, + PIPE_FORMAT_R32G32_USCALED, + PIPE_FORMAT_R32G32B32_USCALED, + PIPE_FORMAT_R32G32B32A32_USCALED, + PIPE_FORMAT_R32_SNORM, + PIPE_FORMAT_R32G32_SNORM, + PIPE_FORMAT_R32G32B32_SNORM, + PIPE_FORMAT_R32G32B32A32_SNORM, + PIPE_FORMAT_R32_SSCALED, + PIPE_FORMAT_R32G32_SSCALED, + PIPE_FORMAT_R32G32B32_SSCALED, + PIPE_FORMAT_R32G32B32A32_SSCALED, + PIPE_FORMAT_R16_UNORM, + PIPE_FORMAT_R16G16_UNORM, + PIPE_FORMAT_R16G16B16_UNORM, + PIPE_FORMAT_R16G16B16A16_UNORM, + PIPE_FORMAT_R16_USCALED, + PIPE_FORMAT_R16G16_USCALED, + PIPE_FORMAT_R16G16B16_USCALED, + PIPE_FORMAT_R16G16B16A16_USCALED, + PIPE_FORMAT_R16_SNORM, + PIPE_FORMAT_R16G16_SNORM, + PIPE_FORMAT_R16G16B16_SNORM, + PIPE_FORMAT_R16G16B16A16_SNORM, + PIPE_FORMAT_R16_SSCALED, + PIPE_FORMAT_R16G16_SSCALED, + PIPE_FORMAT_R16G16B16_SSCALED, + PIPE_FORMAT_R16G16B16A16_SSCALED, + PIPE_FORMAT_R8_UNORM, + PIPE_FORMAT_R8G8_UNORM, + PIPE_FORMAT_R8G8B8_UNORM, + PIPE_FORMAT_R8G8B8A8_UNORM, + PIPE_FORMAT_R8G8B8X8_UNORM, + PIPE_FORMAT_R8_USCALED, + PIPE_FORMAT_R8G8_USCALED, + PIPE_FORMAT_R8G8B8_USCALED, + PIPE_FORMAT_R8G8B8A8_USCALED, + PIPE_FORMAT_R8G8B8X8_USCALED, + PIPE_FORMAT_R8_SNORM, + PIPE_FORMAT_R8G8_SNORM, + PIPE_FORMAT_R8G8B8_SNORM, + PIPE_FORMAT_R8G8B8A8_SNORM, + PIPE_FORMAT_R8G8B8X8_SNORM, + PIPE_FORMAT_B6G5R5_SNORM, + PIPE_FORMAT_A8B8G8R8_SNORM, + PIPE_FORMAT_X8B8G8R8_SNORM, + PIPE_FORMAT_R8_SSCALED, + PIPE_FORMAT_R8G8_SSCALED, + PIPE_FORMAT_R8G8B8_SSCALED, + PIPE_FORMAT_R8G8B8A8_SSCALED, + PIPE_FORMAT_R8G8B8X8_SSCALED, + PIPE_FORMAT_R32_FIXED, + PIPE_FORMAT_R32G32_FIXED, + PIPE_FORMAT_R32G32B32_FIXED, + PIPE_FORMAT_R32G32B32A32_FIXED, + + PIPE_FORMAT_L8_SRGB, + PIPE_FORMAT_A8L8_SRGB, + PIPE_FORMAT_R8G8B8_SRGB, + PIPE_FORMAT_R8G8B8A8_SRGB, + PIPE_FORMAT_R8G8B8X8_SRGB, + PIPE_FORMAT_A8R8G8B8_SRGB, + PIPE_FORMAT_X8R8G8B8_SRGB, + PIPE_FORMAT_B8G8R8A8_SRGB, + PIPE_FORMAT_B8G8R8X8_SRGB, + + PIPE_FORMAT_X8UB8UG8SR8S_NORM, + PIPE_FORMAT_B6UG5SR5S_NORM, + + PIPE_FORMAT_DXT1_RGB, + PIPE_FORMAT_DXT1_RGBA, + PIPE_FORMAT_DXT3_RGBA, + PIPE_FORMAT_DXT5_RGBA, + + PIPE_FORMAT_DXT1_SRGB, + PIPE_FORMAT_DXT1_SRGBA, + PIPE_FORMAT_DXT3_SRGBA, + PIPE_FORMAT_DXT5_SRGBA, +}; + + +struct pipe_format_block +{ + unsigned size; + unsigned width; + unsigned height; +}; + diff --git a/src/gallium/state_trackers/python/p_state.i b/src/gallium/state_trackers/python/p_state.i new file mode 100644 index 00000000000..7f5760b3b66 --- /dev/null +++ b/src/gallium/state_trackers/python/p_state.i @@ -0,0 +1,109 @@ + /************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * SWIG interface definion for Gallium types. + * + * @author Jose Fonseca <[email protected]> + */ + +%module gallium; + +%ignore winsys; +%ignore pipe_vertex_buffer::buffer; + +%include "pipe/p_state.h"; + + +%array_class(struct pipe_stencil_state, StencilArray); + + +%extend pipe_framebuffer_state { + + pipe_framebuffer_state(void) { + return CALLOC_STRUCT(pipe_framebuffer_state); + } + + ~pipe_framebuffer_state() { + unsigned index; + for(index = 0; index < PIPE_MAX_COLOR_BUFS; ++index) + pipe_surface_reference(&$self->cbufs[index], NULL); + pipe_surface_reference(&$self->zsbuf, NULL); + FREE($self); + } + + void + set_cbuf(unsigned index, struct pipe_surface *surface) { + pipe_surface_reference(&$self->cbufs[index], surface); + } + + void + set_zsbuf(struct pipe_surface *surface) { + pipe_surface_reference(&$self->zsbuf, surface); + } + +}; + + +%extend pipe_shader_state { + + pipe_shader_state(const char *text, unsigned num_tokens = 1024) { + struct tgsi_token *tokens; + struct pipe_shader_state *shader; + + tokens = MALLOC(num_tokens * sizeof(struct tgsi_token)); + if(!tokens) + goto error1; + + if(tgsi_text_translate(text, tokens, num_tokens ) != TRUE) + goto error2; + + shader = CALLOC_STRUCT(pipe_shader_state); + if(!shader) + goto error3; + + shader->tokens = tokens; + + return shader; + +error3: +error2: + FREE(tokens); +error1: + return NULL; + } + + ~pipe_shader_state() { + FREE((void*)$self->tokens); + FREE($self); + } + + void dump(unsigned flags = 0) { + tgsi_dump($self->tokens, flags); + } +} diff --git a/src/gallium/state_trackers/python/p_texture.i b/src/gallium/state_trackers/python/p_texture.i new file mode 100644 index 00000000000..08ba0ebe4d0 --- /dev/null +++ b/src/gallium/state_trackers/python/p_texture.i @@ -0,0 +1,232 @@ + /************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * SWIG interface definion for Gallium types. + * + * @author Jose Fonseca <[email protected]> + */ + + +%nodefaultctor pipe_texture; +%nodefaultctor pipe_surface; +%nodefaultctor st_buffer; + +%nodefaultdtor pipe_texture; +%nodefaultdtor pipe_surface; +%nodefaultdtor st_buffer; + +%ignore pipe_texture::screen; + +%ignore pipe_surface::winsys; +%immutable pipe_surface::texture; +%immutable pipe_surface::buffer; + +%newobject pipe_texture::get_surface; + + +%extend pipe_texture { + + ~pipe_texture() { + struct pipe_texture *ptr = $self; + pipe_texture_reference(&ptr, NULL); + } + + unsigned get_width(unsigned level=0) { + return $self->width[level]; + } + + unsigned get_height(unsigned level=0) { + return $self->height[level]; + } + + unsigned get_depth(unsigned level=0) { + return $self->depth[level]; + } + + unsigned get_nblocksx(unsigned level=0) { + return $self->nblocksx[level]; + } + + unsigned get_nblocksy(unsigned level=0) { + return $self->nblocksy[level]; + } + + /** Get a surface which is a "view" into a texture */ + struct pipe_surface * + get_surface(unsigned face=0, unsigned level=0, unsigned zslice=0, unsigned usage=0 ) + { + struct pipe_screen *screen = $self->screen; + return screen->get_tex_surface(screen, $self, face, level, zslice, usage); + } + +}; + + +%extend pipe_surface { + + ~pipe_surface() { + struct pipe_surface *ptr = $self; + pipe_surface_reference(&ptr, NULL); + } + + // gets mapped to pipe_surface_map automatically + void * map( unsigned flags ); + + // gets mapped to pipe_surface_unmap automatically + void unmap( void ); + + void + get_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, char *raw, unsigned stride) { + pipe_get_tile_raw($self, x, y, w, h, raw, stride); + } + + void + put_tile_raw(unsigned x, unsigned y, unsigned w, unsigned h, const char *raw, unsigned stride) { + pipe_put_tile_raw($self, x, y, w, h, raw, stride); + } + + void + get_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, float *rgba) { + pipe_get_tile_rgba($self, x, y, w, h, rgba); + } + + void + put_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba) { + pipe_put_tile_rgba($self, x, y, w, h, rgba); + } + + void + get_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, unsigned *z) { + pipe_get_tile_z($self, x, y, w, h, z); + } + + void + put_tile_z(unsigned x, unsigned y, unsigned w, unsigned h, const unsigned *z) { + pipe_put_tile_z($self, x, y, w, h, z); + } + + void + sample_rgba(float *rgba) { + st_sample_surface($self, rgba); + } + + unsigned + compare_tile_rgba(unsigned x, unsigned y, unsigned w, unsigned h, const float *rgba, float tol = 0.0) + { + float *rgba2; + const float *p1; + const float *p2; + unsigned i, j, n; + + rgba2 = MALLOC(h*w*4*sizeof(float)); + if(!rgba2) + return ~0; + + pipe_get_tile_rgba($self, x, y, w, h, rgba2); + + p1 = rgba; + p2 = rgba2; + n = 0; + for(i = h*w; i; --i) { + unsigned differs = 0; + for(j = 4; j; --j) { + float delta = *p2++ - *p1++; + if (delta < -tol || delta > tol) + differs = 1; + } + n += differs; + } + + FREE(rgba2); + + return n; + } + +}; + +struct st_buffer { +}; + +%extend st_buffer { + + ~st_buffer() { + st_buffer_destroy($self); + } + + unsigned __len__(void) + { + assert($self->buffer->refcount); + return $self->buffer->size; + } + + %cstring_output_allocate_size(char **STRING, int *LENGTH, free(*$1)); + void read(char **STRING, int *LENGTH) + { + struct pipe_screen *screen = $self->st_dev->screen; + const char *map; + + assert($self->buffer->refcount); + + *LENGTH = $self->buffer->size; + *STRING = (char *) malloc($self->buffer->size); + if(!*STRING) + return; + + map = pipe_buffer_map(screen, $self->buffer, PIPE_BUFFER_USAGE_CPU_READ); + if(map) { + memcpy(*STRING, map, $self->buffer->size); + pipe_buffer_unmap(screen, $self->buffer); + } + } + + %cstring_input_binary(const char *STRING, unsigned LENGTH); + void write(const char *STRING, unsigned LENGTH, unsigned offset = 0) + { + struct pipe_screen *screen = $self->st_dev->screen; + char *map; + + assert($self->buffer->refcount); + + if(offset > $self->buffer->size) { + PyErr_SetString(PyExc_ValueError, "offset must be smaller than buffer size"); + return; + } + + if(offset + LENGTH > $self->buffer->size) { + PyErr_SetString(PyExc_ValueError, "data length must fit inside the buffer"); + return; + } + + map = pipe_buffer_map(screen, $self->buffer, PIPE_BUFFER_USAGE_CPU_WRITE); + if(map) { + memcpy(map + offset, STRING, LENGTH); + pipe_buffer_unmap(screen, $self->buffer); + } + } +}; diff --git a/src/gallium/state_trackers/python/retrace/README b/src/gallium/state_trackers/python/retrace/README new file mode 100644 index 00000000000..822cd114044 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/README @@ -0,0 +1,17 @@ +This is an application written in python to replay the traces captured by the + trace pipe driver. + + +To use it follow the instructions in src/gallium/drivers/trace/README and +src/gallium/state_trackers/python/README, and then do + + python src/gallium/state_trackers/python/samples/retrace/interpreter.py filename.trace + + +This is still work in progress: +- not everything is captured/replayed + - surface/textures contents +- any tiny error will result in a crash + +-- +Jose Fonseca <[email protected]> diff --git a/src/gallium/state_trackers/python/retrace/format.py b/src/gallium/state_trackers/python/retrace/format.py new file mode 100755 index 00000000000..0bf6baf0b94 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/format.py @@ -0,0 +1,100 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial portions +# of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +########################################################################## + + +class Formatter: + '''Plain formatter''' + + def __init__(self, stream): + self.stream = stream + + def text(self, text): + self.stream.write(text) + + def newline(self): + self.text('\n') + + def function(self, name): + self.text(name) + + def variable(self, name): + self.text(name) + + def literal(self, value): + self.text(str(value)) + + def address(self, addr): + self.text(str(addr)) + + +class AnsiFormatter(Formatter): + '''Formatter for plain-text files which outputs ANSI escape codes. See + http://en.wikipedia.org/wiki/ANSI_escape_code for more information + concerning ANSI escape codes. + ''' + + _csi = '\33[' + + _normal = '0m' + _bold = '1m' + _italic = '3m' + _red = '31m' + _green = '32m' + _blue = '34m' + + def _escape(self, code): + self.text(self._csi + code) + + def function(self, name): + self._escape(self._bold) + Formatter.function(self, name) + self._escape(self._normal) + + def variable(self, name): + self._escape(self._italic) + Formatter.variable(self, name) + self._escape(self._normal) + + def literal(self, value): + self._escape(self._blue) + Formatter.literal(self, value) + self._escape(self._normal) + + def address(self, value): + self._escape(self._green) + Formatter.address(self, value) + self._escape(self._normal) + + + +def DefaultFormatter(stream): + if stream.isatty(): + return AnsiFormatter(stream) + else: + return Formatter(stream) + diff --git a/src/gallium/state_trackers/python/retrace/interpreter.py b/src/gallium/state_trackers/python/retrace/interpreter.py new file mode 100755 index 00000000000..f418f80d7b4 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/interpreter.py @@ -0,0 +1,578 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial portions +# of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +########################################################################## + + +import sys +import struct + +import gallium +import model +import parser + + +def make_image(surface): + pixels = gallium.FloatArray(surface.height*surface.width*4) + surface.get_tile_rgba(0, 0, surface.width, surface.height, pixels) + + import Image + outimage = Image.new( + mode='RGB', + size=(surface.width, surface.height), + color=(0,0,0)) + outpixels = outimage.load() + for y in range(0, surface.height): + for x in range(0, surface.width): + offset = (y*surface.width + x)*4 + r, g, b, a = [int(pixels[offset + ch]*255) for ch in range(4)] + outpixels[x, y] = r, g, b + return outimage + +def save_image(filename, surface): + outimage = make_image(surface) + outimage.save(filename, "PNG") + +def show_image(surface): + outimage = make_image(surface) + + import Tkinter as tk + from PIL import Image, ImageTk + root = tk.Tk() + + root.title('background image') + + image1 = ImageTk.PhotoImage(outimage) + w = image1.width() + h = image1.height() + x = 100 + y = 100 + root.geometry("%dx%d+%d+%d" % (w, h, x, y)) + panel1 = tk.Label(root, image=image1) + panel1.pack(side='top', fill='both', expand='yes') + panel1.image = image1 + root.mainloop() + + + + +class Struct: + """C-like struct""" + + # A basic Python class can pass as a C-like structure + pass + + +struct_factories = { + "pipe_blend_color": gallium.BlendColor, + "pipe_blend_state": gallium.Blend, + #"pipe_clip_state": gallium.Clip, + #"pipe_constant_buffer": gallium.ConstantBuffer, + "pipe_depth_state": gallium.Depth, + "pipe_stencil_state": gallium.Stencil, + "pipe_alpha_state": gallium.Alpha, + "pipe_depth_stencil_alpha_state": gallium.DepthStencilAlpha, + "pipe_format_block": gallium.FormatBlock, + #"pipe_framebuffer_state": gallium.Framebuffer, + "pipe_poly_stipple": gallium.PolyStipple, + "pipe_rasterizer_state": gallium.Rasterizer, + "pipe_sampler_state": gallium.Sampler, + "pipe_scissor_state": gallium.Scissor, + #"pipe_shader_state": gallium.Shader, + #"pipe_vertex_buffer": gallium.VertexBuffer, + "pipe_vertex_element": gallium.VertexElement, + "pipe_viewport_state": gallium.Viewport, + #"pipe_texture": gallium.Texture, +} + + +member_array_factories = { + "pipe_rasterizer_state": {"sprite_coord_mode": gallium.ByteArray}, + "pipe_poly_stipple": {"stipple": gallium.UnsignedArray}, + "pipe_viewport_state": {"scale": gallium.FloatArray, "translate": gallium.FloatArray}, + #"pipe_clip_state": {"ucp": gallium.FloatArray}, + "pipe_depth_stencil_alpha_state": {"stencil": gallium.StencilArray}, + "pipe_blend_color": {"color": gallium.FloatArray}, + "pipe_sampler_state": {"border_color": gallium.FloatArray}, +} + + +class Translator(model.Visitor): + """Translate model arguments into regular Python objects""" + + def __init__(self, interpreter): + self.interpreter = interpreter + self.result = None + + def visit(self, node): + self.result = None + node.visit(self) + return self.result + + def visit_literal(self, node): + self.result = node.value + + def visit_named_constant(self, node): + # lookup the named constant in the gallium module + self.result = getattr(gallium, node.name) + + def visit_array(self, node): + array = [] + for element in node.elements: + array.append(self.visit(element)) + self.result = array + + def visit_struct(self, node): + struct_factory = struct_factories.get(node.name, Struct) + struct = struct_factory() + for member_name, member_node in node.members: + member_value = self.visit(member_node) + try: + array_factory = member_array_factories[node.name][member_name] + except KeyError: + pass + else: + assert isinstance(member_value, list) + array = array_factory(len(member_value)) + for i in range(len(member_value)): + array[i] = member_value[i] + member_value = array + #print node.name, member_name, member_value + assert isinstance(struct, Struct) or hasattr(struct, member_name) + setattr(struct, member_name, member_value) + self.result = struct + + def visit_pointer(self, node): + self.result = self.interpreter.lookup_object(node.address) + + +class Object: + + def __init__(self, interpreter, real): + self.interpreter = interpreter + self.real = real + + +class Global(Object): + + def __init__(self, interpreter, real): + self.interpreter = interpreter + self.real = real + + def pipe_winsys_create(self): + return Winsys(self.interpreter, gallium.Device()) + + def pipe_screen_create(self, winsys): + return Screen(self.interpreter, winsys.real) + + def pipe_context_create(self, screen): + context = screen.real.context_create() + return Context(self.interpreter, context) + + +class Winsys(Object): + + def __init__(self, interpreter, real): + self.interpreter = interpreter + self.real = real + + def get_name(self): + pass + + def user_buffer_create(self, data, size): + # We don't really care to distinguish between user and regular buffers + buffer = self.real.buffer_create(size, + 4, + gallium.PIPE_BUFFER_USAGE_CPU_READ | + gallium.PIPE_BUFFER_USAGE_CPU_WRITE ) + assert size == len(data) + buffer.write(data) + return buffer + + def buffer_create(self, alignment, usage, size): + return self.real.buffer_create(size, alignment, usage) + + def buffer_destroy(self, buffer): + pass + + def buffer_write(self, buffer, data, size): + assert size == len(data) + buffer.write(data) + + def fence_finish(self, fence, flags): + pass + + def fence_reference(self, dst, src): + pass + + def flush_frontbuffer(self, surface): + pass + + def surface_alloc(self): + return None + + def surface_release(self, surface): + pass + + +class Screen(Object): + + def destroy(self): + pass + + def get_name(self): + pass + + def get_vendor(self): + pass + + def get_param(self, param): + pass + + def get_paramf(self, param): + pass + + def is_format_supported(self, format, target, tex_usage, geom_flags): + return self.real.is_format_supported(format, target, tex_usage, geom_flags) + + def texture_create(self, template): + return self.real.texture_create( + format = template.format, + width = template.width[0], + height = template.height[0], + depth = template.depth[0], + last_level = template.last_level, + target = template.target, + tex_usage = template.tex_usage, + ) + + def texture_destroy(self, texture): + self.interpreter.unregister_object(texture) + + def texture_release(self, surface): + pass + + def get_tex_surface(self, texture, face, level, zslice, usage): + return texture.get_surface(face, level, zslice, usage) + + def tex_surface_destroy(self, surface): + self.interpreter.unregister_object(surface) + + def tex_surface_release(self, surface): + pass + + def surface_write(self, surface, data, stride, size): + assert surface.nblocksy * stride == size + surface.put_tile_raw(0, 0, surface.width, surface.height, data, stride) + + +class Context(Object): + + def __init__(self, interpreter, real): + Object.__init__(self, interpreter, real) + self.cbufs = [] + self.zsbuf = None + self.vbufs = [] + self.velems = [] + + def destroy(self): + pass + + def create_blend_state(self, state): + return state + + def bind_blend_state(self, state): + if state is not None: + self.real.set_blend(state) + + def delete_blend_state(self, state): + pass + + def create_sampler_state(self, state): + return state + + def delete_sampler_state(self, state): + pass + + def bind_sampler_states(self, n, states): + for i in range(n): + self.real.set_sampler(i, states[i]) + + def create_rasterizer_state(self, state): + return state + + def bind_rasterizer_state(self, state): + if state is not None: + self.real.set_rasterizer(state) + + def delete_rasterizer_state(self, state): + pass + + def create_depth_stencil_alpha_state(self, state): + return state + + def bind_depth_stencil_alpha_state(self, state): + if state is not None: + self.real.set_depth_stencil_alpha(state) + + def delete_depth_stencil_alpha_state(self, state): + pass + + def create_fs_state(self, state): + tokens = str(state.tokens) + shader = gallium.Shader(tokens) + return shader + + create_vs_state = create_fs_state + + def bind_fs_state(self, state): + self.real.set_fragment_shader(state) + + def bind_vs_state(self, state): + self.real.set_vertex_shader(state) + + def delete_fs_state(self, state): + pass + + delete_vs_state = delete_fs_state + + def set_blend_color(self, state): + self.real.set_blend_color(state) + + def set_clip_state(self, state): + _state = gallium.Clip() + _state.nr = state.nr + if state.nr: + # FIXME + ucp = gallium.FloatArray(gallium.PIPE_MAX_CLIP_PLANES*4) + for i in range(len(state.ucp)): + for j in range(len(state.ucp[i])): + ucp[i*4 + j] = state.ucp[i][j] + _state.ucp = ucp + self.real.set_clip(_state) + + def set_constant_buffer(self, shader, index, state): + if state is not None: + self.real.set_constant_buffer(shader, index, state.buffer) + + if 1: + data = state.buffer.read() + format = '4f' + index = 0 + for offset in range(0, len(data), struct.calcsize(format)): + x, y, z, w = struct.unpack_from(format, data, offset) + sys.stdout.write('\tCONST[%2u] = {%10.4f, %10.4f, %10.4f, %10.4f}\n' % (index, x, y, z, w)) + index += 1 + + def set_framebuffer_state(self, state): + _state = gallium.Framebuffer() + _state.width = state.width + _state.height = state.height + _state.num_cbufs = state.num_cbufs + for i in range(len(state.cbufs)): + _state.set_cbuf(i, state.cbufs[i]) + _state.set_zsbuf(state.zsbuf) + self.real.set_framebuffer(_state) + + self.cbufs = state.cbufs + self.zsbuf = state.zsbuf + + def set_polygon_stipple(self, state): + self.real.set_polygon_stipple(state) + + def set_scissor_state(self, state): + self.real.set_scissor(state) + + def set_viewport_state(self, state): + self.real.set_viewport(state) + + def set_sampler_textures(self, n, textures): + for i in range(n): + self.real.set_sampler_texture(i, textures[i]) + + def set_vertex_buffers(self, n, vbufs): + self.vbufs = vbufs[0:n] + for i in range(n): + vbuf = vbufs[i] + self.real.set_vertex_buffer( + i, + pitch = vbuf.pitch, + max_index = vbuf.max_index, + buffer_offset = vbuf.buffer_offset, + buffer = vbuf.buffer, + ) + + def set_vertex_elements(self, n, elements): + self.velems = elements[0:n] + for i in range(n): + self.real.set_vertex_element(i, elements[i]) + self.real.set_vertex_elements(n) + + def set_edgeflags(self, bitfield): + # FIXME + pass + + def dump_vertices(self, start, count): + for index in range(start, start + count): + if index >= start + 16: + sys.stdout.write('\t...\n') + break + sys.stdout.write('\t{\n') + for velem in self.velems: + vbuf = self.vbufs[velem.vertex_buffer_index] + + offset = vbuf.buffer_offset + velem.src_offset + vbuf.pitch*index + format = { + gallium.PIPE_FORMAT_R32_FLOAT: 'f', + gallium.PIPE_FORMAT_R32G32_FLOAT: '2f', + gallium.PIPE_FORMAT_R32G32B32_FLOAT: '3f', + gallium.PIPE_FORMAT_R32G32B32A32_FLOAT: '4f', + gallium.PIPE_FORMAT_B8G8R8A8_UNORM: '4B', + }[velem.src_format] + + data = vbuf.buffer.read() + values = struct.unpack_from(format, data, offset) + sys.stdout.write('\t\t{' + ', '.join(map(str, values)) + '},\n') + assert len(values) == velem.nr_components + sys.stdout.write('\t},\n') + + def dump_indices(self, ibuf, isize, start, count): + format = { + 1: 'B', + 2: 'H', + 4: 'I', + }[isize] + + assert struct.calcsize(format) == isize + + data = ibuf.read() + maxindex, minindex = 0, 0xffffffff + + sys.stdout.write('\t{\n') + for i in range(start, start + count): + if i >= start + 16: + sys.stdout.write('\t...\n') + break + offset = i*isize + index, = struct.unpack_from(format, data, offset) + sys.stdout.write('\t\t%u,\n' % index) + minindex = min(minindex, index) + maxindex = max(maxindex, index) + sys.stdout.write('\t},\n') + + return minindex, maxindex + + def draw_arrays(self, mode, start, count): + self.dump_vertices(start, count) + + self.real.draw_arrays(mode, start, count) + + def draw_elements(self, indexBuffer, indexSize, mode, start, count): + minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) + self.dump_vertices(minindex, maxindex - minindex) + + self.real.draw_elements(indexBuffer, indexSize, mode, start, count) + + def draw_range_elements(self, indexBuffer, indexSize, minIndex, maxIndex, mode, start, count): + minindex, maxindex = self.dump_indices(indexBuffer, indexSize, start, count) + minindex = min(minindex, minIndex) + maxindex = min(maxindex, maxIndex) + self.dump_vertices(minindex, maxindex - minindex) + + self.real.draw_range_elements(indexBuffer, indexSize, minIndex, maxIndex, mode, start, count) + + def flush(self, flags): + self.real.flush(flags) + if flags & gallium.PIPE_FLUSH_FRAME: + self._update() + return None + + def clear(self, surface, value): + self.real.surface_clear(surface, value) + + def _update(self): + self.real.flush() + + if self.cbufs and self.cbufs[0]: + show_image(self.cbufs[0]) + + +class Interpreter(parser.TraceDumper): + + ignore_calls = set(( + ('pipe_screen', 'is_format_supported'), + ('pipe_screen', 'get_param'), + ('pipe_screen', 'get_paramf'), + )) + + def __init__(self, stream): + parser.TraceDumper.__init__(self, stream) + self.objects = {} + self.result = None + self.globl = Global(self, None) + + def register_object(self, address, object): + self.objects[address] = object + + def unregister_object(self, object): + # FIXME: + pass + + def lookup_object(self, address): + return self.objects[address] + + def interpret(self, trace): + for call in trace.calls: + self.interpret_call(call) + + def handle_call(self, call): + + if (call.klass, call.method) in self.ignore_calls: + return + + parser.TraceDumper.handle_call(self, call) + + args = [self.interpret_arg(arg) for name, arg in call.args] + + if call.klass: + obj = args[0] + args = args[1:] + else: + obj = self.globl + + method = getattr(obj, call.method) + ret = method(*args) + + if call.ret and isinstance(call.ret, model.Pointer): + self.register_object(call.ret.address, ret) + + def interpret_arg(self, node): + translator = Translator(self) + return translator.visit(node) + + +if __name__ == '__main__': + parser.main(Interpreter) diff --git a/src/gallium/state_trackers/python/retrace/model.py b/src/gallium/state_trackers/python/retrace/model.py new file mode 100755 index 00000000000..ae0f4327d76 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/model.py @@ -0,0 +1,211 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial portions +# of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +########################################################################## + + +'''Trace data model.''' + + +import sys +import string +import format + +try: + from cStringIO import StringIO +except ImportError: + from StringIO import StringIO + + +class Node: + + def visit(self, visitor): + raise NotImplementedError + + def __str__(self): + stream = StringIO() + formatter = format.DefaultFormatter(stream) + pretty_printer = PrettyPrinter(formatter) + self.visit(pretty_printer) + return stream.getvalue() + + +class Literal(Node): + + def __init__(self, value): + self.value = value + + def visit(self, visitor): + visitor.visit_literal(self) + + +class NamedConstant(Node): + + def __init__(self, name): + self.name = name + + def visit(self, visitor): + visitor.visit_named_constant(self) + + +class Array(Node): + + def __init__(self, elements): + self.elements = elements + + def visit(self, visitor): + visitor.visit_array(self) + + +class Struct(Node): + + def __init__(self, name, members): + self.name = name + self.members = members + + def visit(self, visitor): + visitor.visit_struct(self) + + +class Pointer(Node): + + def __init__(self, address): + self.address = address + + def visit(self, visitor): + visitor.visit_pointer(self) + + +class Call: + + def __init__(self, klass, method, args, ret): + self.klass = klass + self.method = method + self.args = args + self.ret = ret + + def visit(self, visitor): + visitor.visit_call(self) + + +class Trace: + + def __init__(self, calls): + self.calls = calls + + def visit(self, visitor): + visitor.visit_trace(self) + + +class Visitor: + + def visit_literal(self, node): + raise NotImplementedError + + def visit_named_constant(self, node): + raise NotImplementedError + + def visit_array(self, node): + raise NotImplementedError + + def visit_struct(self, node): + raise NotImplementedError + + def visit_pointer(self, node): + raise NotImplementedError + + def visit_call(self, node): + raise NotImplementedError + + def visit_trace(self, node): + raise NotImplementedError + + +class PrettyPrinter: + + def __init__(self, formatter): + self.formatter = formatter + + def visit_literal(self, node): + if isinstance(node.value, basestring): + if len(node.value) >= 4096 or node.value.strip(string.printable): + self.formatter.text('...') + return + + self.formatter.literal('"' + node.value + '"') + return + + self.formatter.literal(repr(node.value)) + + def visit_named_constant(self, node): + self.formatter.literal(node.name) + + def visit_array(self, node): + self.formatter.text('{') + sep = '' + for value in node.elements: + self.formatter.text(sep) + value.visit(self) + sep = ', ' + self.formatter.text('}') + + def visit_struct(self, node): + self.formatter.text('{') + sep = '' + for name, value in node.members: + self.formatter.text(sep) + self.formatter.variable(name) + self.formatter.text(' = ') + value.visit(self) + sep = ', ' + self.formatter.text('}') + + def visit_pointer(self, node): + self.formatter.address(node.address) + + def visit_call(self, node): + if node.klass is not None: + self.formatter.function(node.klass + '::' + node.method) + else: + self.formatter.function(node.method) + self.formatter.text('(') + sep = '' + for name, value in node.args: + self.formatter.text(sep) + self.formatter.variable(name) + self.formatter.text(' = ') + value.visit(self) + sep = ', ' + self.formatter.text(')') + if node.ret is not None: + self.formatter.text(' = ') + node.ret.visit(self) + + def visit_trace(self, node): + for call in node.calls: + call.visit(self) + self.formatter.newline() + diff --git a/src/gallium/state_trackers/python/retrace/parser.py b/src/gallium/state_trackers/python/retrace/parser.py new file mode 100755 index 00000000000..5205f2d8dd5 --- /dev/null +++ b/src/gallium/state_trackers/python/retrace/parser.py @@ -0,0 +1,357 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial portions +# of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +########################################################################## + + +import sys +import xml.parsers.expat +import binascii + +from model import * + + +ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF = range(4) + + +class XmlToken: + + def __init__(self, type, name_or_data, attrs = None, line = None, column = None): + assert type in (ELEMENT_START, ELEMENT_END, CHARACTER_DATA, EOF) + self.type = type + self.name_or_data = name_or_data + self.attrs = attrs + self.line = line + self.column = column + + def __str__(self): + if self.type == ELEMENT_START: + return '<' + self.name_or_data + ' ...>' + if self.type == ELEMENT_END: + return '</' + self.name_or_data + '>' + if self.type == CHARACTER_DATA: + return self.name_or_data + if self.type == EOF: + return 'end of file' + assert 0 + + +class XmlTokenizer: + """Expat based XML tokenizer.""" + + def __init__(self, fp, skip_ws = True): + self.fp = fp + self.tokens = [] + self.index = 0 + self.final = False + self.skip_ws = skip_ws + + self.character_pos = 0, 0 + self.character_data = '' + + self.parser = xml.parsers.expat.ParserCreate() + self.parser.StartElementHandler = self.handle_element_start + self.parser.EndElementHandler = self.handle_element_end + self.parser.CharacterDataHandler = self.handle_character_data + + def handle_element_start(self, name, attributes): + self.finish_character_data() + line, column = self.pos() + token = XmlToken(ELEMENT_START, name, attributes, line, column) + self.tokens.append(token) + + def handle_element_end(self, name): + self.finish_character_data() + line, column = self.pos() + token = XmlToken(ELEMENT_END, name, None, line, column) + self.tokens.append(token) + + def handle_character_data(self, data): + if not self.character_data: + self.character_pos = self.pos() + self.character_data += data + + def finish_character_data(self): + if self.character_data: + if not self.skip_ws or not self.character_data.isspace(): + line, column = self.character_pos + token = XmlToken(CHARACTER_DATA, self.character_data, None, line, column) + self.tokens.append(token) + self.character_data = '' + + def next(self): + size = 16*1024 + while self.index >= len(self.tokens) and not self.final: + self.tokens = [] + self.index = 0 + data = self.fp.read(size) + self.final = len(data) < size + data = data.rstrip('\0') + try: + self.parser.Parse(data, self.final) + except xml.parsers.expat.ExpatError, e: + #if e.code == xml.parsers.expat.errors.XML_ERROR_NO_ELEMENTS: + if e.code == 3: + pass + else: + raise e + if self.index >= len(self.tokens): + line, column = self.pos() + token = XmlToken(EOF, None, None, line, column) + else: + token = self.tokens[self.index] + self.index += 1 + return token + + def pos(self): + return self.parser.CurrentLineNumber, self.parser.CurrentColumnNumber + + +class TokenMismatch(Exception): + + def __init__(self, expected, found): + self.expected = expected + self.found = found + + def __str__(self): + return '%u:%u: %s expected, %s found' % (self.found.line, self.found.column, str(self.expected), str(self.found)) + + + +class XmlParser: + """Base XML document parser.""" + + def __init__(self, fp): + self.tokenizer = XmlTokenizer(fp) + self.consume() + + def consume(self): + self.token = self.tokenizer.next() + + def match_element_start(self, name): + return self.token.type == ELEMENT_START and self.token.name_or_data == name + + def match_element_end(self, name): + return self.token.type == ELEMENT_END and self.token.name_or_data == name + + def element_start(self, name): + while self.token.type == CHARACTER_DATA: + self.consume() + if self.token.type != ELEMENT_START: + raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) + if self.token.name_or_data != name: + raise TokenMismatch(XmlToken(ELEMENT_START, name), self.token) + attrs = self.token.attrs + self.consume() + return attrs + + def element_end(self, name): + while self.token.type == CHARACTER_DATA: + self.consume() + if self.token.type != ELEMENT_END: + raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) + if self.token.name_or_data != name: + raise TokenMismatch(XmlToken(ELEMENT_END, name), self.token) + self.consume() + + def character_data(self, strip = True): + data = '' + while self.token.type == CHARACTER_DATA: + data += self.token.name_or_data + self.consume() + if strip: + data = data.strip() + return data + + +class TraceParser(XmlParser): + + def parse(self): + self.element_start('trace') + while self.token.type not in (ELEMENT_END, EOF): + call = self.parse_call() + self.handle_call(call) + if self.token.type != EOF: + self.element_end('trace') + + def parse_call(self): + attrs = self.element_start('call') + klass = attrs['class'] + method = attrs['method'] + args = [] + ret = None + while self.token.type == ELEMENT_START: + if self.token.name_or_data == 'arg': + arg = self.parse_arg() + args.append(arg) + elif self.token.name_or_data == 'ret': + ret = self.parse_ret() + elif self.token.name_or_data == 'call': + # ignore nested function calls + self.parse_call() + else: + raise TokenMismatch("<arg ...> or <ret ...>", self.token) + self.element_end('call') + + return Call(klass, method, args, ret) + + def parse_arg(self): + attrs = self.element_start('arg') + name = attrs['name'] + value = self.parse_value() + self.element_end('arg') + + return name, value + + def parse_ret(self): + attrs = self.element_start('ret') + value = self.parse_value() + self.element_end('ret') + + return value + + def parse_value(self): + expected_tokens = ('null', 'bool', 'int', 'uint', 'float', 'string', 'enum', 'array', 'struct', 'ptr', 'bytes') + if self.token.type == ELEMENT_START: + if self.token.name_or_data in expected_tokens: + method = getattr(self, 'parse_' + self.token.name_or_data) + return method() + raise TokenMismatch(" or " .join(expected_tokens), self.token) + + def parse_null(self): + self.element_start('null') + self.element_end('null') + return Literal(None) + + def parse_bool(self): + self.element_start('bool') + value = int(self.character_data()) + self.element_end('bool') + return Literal(value) + + def parse_int(self): + self.element_start('int') + value = int(self.character_data()) + self.element_end('int') + return Literal(value) + + def parse_uint(self): + self.element_start('uint') + value = int(self.character_data()) + self.element_end('uint') + return Literal(value) + + def parse_float(self): + self.element_start('float') + value = float(self.character_data()) + self.element_end('float') + return Literal(value) + + def parse_enum(self): + self.element_start('enum') + name = self.character_data() + self.element_end('enum') + return NamedConstant(name) + + def parse_string(self): + self.element_start('string') + value = self.character_data() + self.element_end('string') + return Literal(value) + + def parse_bytes(self): + self.element_start('bytes') + value = binascii.a2b_hex(self.character_data()) + self.element_end('bytes') + return Literal(value) + + def parse_array(self): + self.element_start('array') + elems = [] + while self.token.type != ELEMENT_END: + elems.append(self.parse_elem()) + self.element_end('array') + return Array(elems) + + def parse_elem(self): + self.element_start('elem') + value = self.parse_value() + self.element_end('elem') + return value + + def parse_struct(self): + attrs = self.element_start('struct') + name = attrs['name'] + members = [] + while self.token.type != ELEMENT_END: + members.append(self.parse_member()) + self.element_end('struct') + return Struct(name, members) + + def parse_member(self): + attrs = self.element_start('member') + name = attrs['name'] + value = self.parse_value() + self.element_end('member') + + return name, value + + def parse_ptr(self): + self.element_start('ptr') + address = self.character_data() + self.element_end('ptr') + + return Pointer(address) + + def handle_call(self, call): + pass + + +class TraceDumper(TraceParser): + + def __init__(self, fp): + TraceParser.__init__(self, fp) + self.formatter = format.DefaultFormatter(sys.stdout) + self.pretty_printer = PrettyPrinter(self.formatter) + + def handle_call(self, call): + call.visit(self.pretty_printer) + self.formatter.newline() + + +def main(ParserFactory): + for arg in sys.argv[1:]: + if arg.endswith('.gz'): + import gzip + stream = gzip.GzipFile(arg, 'rt') + else: + stream = open(arg, 'rt') + parser = ParserFactory(stream) + parser.parse() + + +if __name__ == '__main__': + main(TraceDumper) diff --git a/src/gallium/state_trackers/python/samples/tri.py b/src/gallium/state_trackers/python/samples/tri.py new file mode 100644 index 00000000000..193479f7d6c --- /dev/null +++ b/src/gallium/state_trackers/python/samples/tri.py @@ -0,0 +1,229 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial portions +# of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +########################################################################## + + +from gallium import * + + +def make_image(surface): + pixels = FloatArray(surface.height*surface.width*4) + surface.get_tile_rgba(0, 0, surface.width, surface.height, pixels) + + import Image + outimage = Image.new( + mode='RGB', + size=(surface.width, surface.height), + color=(0,0,0)) + outpixels = outimage.load() + for y in range(0, surface.height): + for x in range(0, surface.width): + offset = (y*surface.width + x)*4 + r, g, b, a = [int(pixels[offset + ch]*255) for ch in range(4)] + outpixels[x, y] = r, g, b + return outimage + +def save_image(filename, surface): + outimage = make_image(surface) + outimage.save(filename, "PNG") + +def show_image(surface): + outimage = make_image(surface) + + import Tkinter as tk + from PIL import Image, ImageTk + root = tk.Tk() + + root.title('background image') + + image1 = ImageTk.PhotoImage(outimage) + w = image1.width() + h = image1.height() + x = 100 + y = 100 + root.geometry("%dx%d+%d+%d" % (w, h, x, y)) + panel1 = tk.Label(root, image=image1) + panel1.pack(side='top', fill='both', expand='yes') + panel1.image = image1 + root.mainloop() + + +def test(dev): + ctx = dev.context_create() + + width = 255 + height = 255 + + # disabled blending/masking + blend = Blend() + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.colormask = PIPE_MASK_RGBA + ctx.set_blend(blend) + + # no-op depth/stencil/alpha + depth_stencil_alpha = DepthStencilAlpha() + ctx.set_depth_stencil_alpha(depth_stencil_alpha) + + # rasterizer + rasterizer = Rasterizer() + rasterizer.front_winding = PIPE_WINDING_CW + rasterizer.cull_mode = PIPE_WINDING_NONE + rasterizer.bypass_clipping = 1 + rasterizer.scissor = 1 + #rasterizer.bypass_vs = 1 + ctx.set_rasterizer(rasterizer) + + # viewport (identity, we setup vertices in wincoords) + viewport = Viewport() + scale = FloatArray(4) + scale[0] = 1.0 + scale[1] = 1.0 + scale[2] = 1.0 + scale[3] = 1.0 + viewport.scale = scale + translate = FloatArray(4) + translate[0] = 0.0 + translate[1] = 0.0 + translate[2] = 0.0 + translate[3] = 0.0 + viewport.translate = translate + ctx.set_viewport(viewport) + + # samplers + sampler = Sampler() + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NONE + sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST + sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST + sampler.normalized_coords = 1 + ctx.set_sampler(0, sampler) + + # scissor + scissor = Scissor() + scissor.minx = 0 + scissor.miny = 0 + scissor.maxx = width + scissor.maxy = height + ctx.set_scissor(scissor) + + clip = Clip() + clip.nr = 0 + ctx.set_clip(clip) + + # framebuffer + cbuf = dev.texture_create( + PIPE_FORMAT_X8R8G8B8_UNORM, + width, height, + tex_usage=PIPE_TEXTURE_USAGE_DISPLAY_TARGET, + ) + _cbuf = cbuf.get_surface(usage = PIPE_BUFFER_USAGE_GPU_READ|PIPE_BUFFER_USAGE_GPU_WRITE) + fb = Framebuffer() + fb.width = width + fb.height = height + fb.num_cbufs = 1 + fb.set_cbuf(0, _cbuf) + ctx.set_framebuffer(fb) + _cbuf.clear_value = 0x00000000 + ctx.surface_clear(_cbuf, _cbuf.clear_value) + del _cbuf + + # vertex shader + vs = Shader(''' + VERT1.1 + DCL IN[0], POSITION, CONSTANT + DCL IN[1], COLOR, CONSTANT + DCL OUT[0], POSITION, CONSTANT + DCL OUT[1], COLOR, CONSTANT + 0:MOV OUT[0], IN[0] + 1:MOV OUT[1], IN[1] + 2:END + ''') + ctx.set_vertex_shader(vs) + + # fragment shader + fs = Shader(''' + FRAG1.1 + DCL IN[0], COLOR, LINEAR + DCL OUT[0], COLOR, CONSTANT + 0:MOV OUT[0], IN[0] + 1:END + ''') + ctx.set_fragment_shader(fs) + + nverts = 3 + nattrs = 2 + verts = FloatArray(nverts * nattrs * 4) + + verts[ 0] = 128.0 # x1 + verts[ 1] = 32.0 # y1 + verts[ 2] = 0.0 # z1 + verts[ 3] = 1.0 # w1 + verts[ 4] = 1.0 # r1 + verts[ 5] = 0.0 # g1 + verts[ 6] = 0.0 # b1 + verts[ 7] = 1.0 # a1 + verts[ 8] = 32.0 # x2 + verts[ 9] = 224.0 # y2 + verts[10] = 0.0 # z2 + verts[11] = 1.0 # w2 + verts[12] = 0.0 # r2 + verts[13] = 1.0 # g2 + verts[14] = 0.0 # b2 + verts[15] = 1.0 # a2 + verts[16] = 224.0 # x3 + verts[17] = 224.0 # y3 + verts[18] = 0.0 # z3 + verts[19] = 1.0 # w3 + verts[20] = 0.0 # r3 + verts[21] = 0.0 # g3 + verts[22] = 1.0 # b3 + verts[23] = 1.0 # a3 + + ctx.draw_vertices(PIPE_PRIM_TRIANGLES, + nverts, + nattrs, + verts) + + ctx.flush() + + show_image(cbuf.get_surface(usage = PIPE_BUFFER_USAGE_CPU_READ|PIPE_BUFFER_USAGE_CPU_WRITE)) + #save_image('tri.png', cbuf.get_surface(usage = PIPE_BUFFER_USAGE_CPU_READ|PIPE_BUFFER_USAGE_CPU_WRITE)) + + + +def main(): + dev = Device() + test(dev) + + +if __name__ == '__main__': + main() diff --git a/src/gallium/state_trackers/python/st_device.c b/src/gallium/state_trackers/python/st_device.c new file mode 100644 index 00000000000..20dd8d269d9 --- /dev/null +++ b/src/gallium/state_trackers/python/st_device.c @@ -0,0 +1,323 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "pipe/p_screen.h" +#include "pipe/p_context.h" +#include "pipe/p_shader_tokens.h" +#include "pipe/p_inlines.h" +#include "cso_cache/cso_context.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "util/u_simple_shaders.h" +#include "trace/tr_screen.h" +#include "trace/tr_context.h" + +#include "st_device.h" +#include "st_winsys.h" + + +static void +st_device_really_destroy(struct st_device *st_dev) +{ + if(st_dev->screen) + st_dev->screen->destroy(st_dev->screen); + + FREE(st_dev); +} + + +void +st_device_destroy(struct st_device *st_dev) +{ + if(!--st_dev->refcount) + st_device_really_destroy(st_dev); +} + + +static struct st_device * +st_device_create_from_st_winsys(const struct st_winsys *st_ws) +{ + struct st_device *st_dev; + + if(!st_ws->screen_create || + !st_ws->context_create) + return NULL; + + st_dev = CALLOC_STRUCT(st_device); + if(!st_dev) + return NULL; + + st_dev->refcount = 1; + st_dev->st_ws = st_ws; + + st_dev->real_screen = st_ws->screen_create(); + if(!st_dev->real_screen) { + st_device_destroy(st_dev); + return NULL; + } + + st_dev->screen = trace_screen_create(st_dev->real_screen); + if(!st_dev->screen) { + st_device_destroy(st_dev); + return NULL; + } + + return st_dev; +} + + +struct st_device * +st_device_create(boolean hardware) { + if(hardware) + return st_device_create_from_st_winsys(&st_hardpipe_winsys); + else + return st_device_create_from_st_winsys(&st_softpipe_winsys); +} + + +void +st_context_destroy(struct st_context *st_ctx) +{ + unsigned i; + + if(st_ctx) { + struct st_device *st_dev = st_ctx->st_dev; + + if(st_ctx->cso) { + cso_delete_vertex_shader(st_ctx->cso, st_ctx->vs); + cso_delete_fragment_shader(st_ctx->cso, st_ctx->fs); + + cso_destroy_context(st_ctx->cso); + } + + if(st_ctx->pipe) + st_ctx->pipe->destroy(st_ctx->pipe); + + for(i = 0; i < PIPE_MAX_SAMPLERS; ++i) + pipe_texture_reference(&st_ctx->sampler_textures[i], NULL); + pipe_texture_reference(&st_ctx->default_texture, NULL); + + FREE(st_ctx); + + if(!--st_dev->refcount) + st_device_really_destroy(st_dev); + } +} + + +struct st_context * +st_context_create(struct st_device *st_dev) +{ + struct st_context *st_ctx; + + st_ctx = CALLOC_STRUCT(st_context); + if(!st_ctx) + return NULL; + + st_ctx->st_dev = st_dev; + ++st_dev->refcount; + + st_ctx->real_pipe = st_dev->st_ws->context_create(st_dev->real_screen); + if(!st_ctx->real_pipe) { + st_context_destroy(st_ctx); + return NULL; + } + + st_ctx->pipe = trace_context_create(st_dev->screen, st_ctx->real_pipe); + if(!st_ctx->pipe) { + st_context_destroy(st_ctx); + return NULL; + } + + st_ctx->cso = cso_create_context(st_ctx->pipe); + if(!st_ctx->cso) { + st_context_destroy(st_ctx); + return NULL; + } + + /* disabled blending/masking */ + { + struct pipe_blend_state blend; + memset(&blend, 0, sizeof(blend)); + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE; + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE; + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO; + blend.colormask = PIPE_MASK_RGBA; + cso_set_blend(st_ctx->cso, &blend); + } + + /* no-op depth/stencil/alpha */ + { + struct pipe_depth_stencil_alpha_state depthstencil; + memset(&depthstencil, 0, sizeof(depthstencil)); + cso_set_depth_stencil_alpha(st_ctx->cso, &depthstencil); + } + + /* rasterizer */ + { + struct pipe_rasterizer_state rasterizer; + memset(&rasterizer, 0, sizeof(rasterizer)); + rasterizer.front_winding = PIPE_WINDING_CW; + rasterizer.cull_mode = PIPE_WINDING_NONE; + rasterizer.bypass_clipping = 1; + /*rasterizer.bypass_vs = 1;*/ + cso_set_rasterizer(st_ctx->cso, &rasterizer); + } + + /* identity viewport */ + { + struct pipe_viewport_state viewport; + viewport.scale[0] = 1.0; + viewport.scale[1] = 1.0; + viewport.scale[2] = 1.0; + viewport.scale[3] = 1.0; + viewport.translate[0] = 0.0; + viewport.translate[1] = 0.0; + viewport.translate[2] = 0.0; + viewport.translate[3] = 0.0; + cso_set_viewport(st_ctx->cso, &viewport); + } + + /* samplers */ + { + struct pipe_sampler_state sampler; + unsigned i; + memset(&sampler, 0, sizeof(sampler)); + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE; + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST; + sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST; + sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST; + sampler.normalized_coords = 1; + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) + cso_single_sampler(st_ctx->cso, i, &sampler); + cso_single_sampler_done(st_ctx->cso); + } + + /* default textures */ + { + struct pipe_screen *screen = st_dev->screen; + struct pipe_texture templat; + struct pipe_surface *surface; + unsigned i; + + memset( &templat, 0, sizeof( templat ) ); + templat.target = PIPE_TEXTURE_2D; + templat.format = PIPE_FORMAT_A8R8G8B8_UNORM; + templat.block.size = 4; + templat.block.width = 1; + templat.block.height = 1; + templat.width[0] = 1; + templat.height[0] = 1; + templat.depth[0] = 1; + templat.last_level = 0; + + st_ctx->default_texture = screen->texture_create( screen, &templat ); + if(st_ctx->default_texture) { + surface = screen->get_tex_surface( screen, + st_ctx->default_texture, 0, 0, 0, + PIPE_BUFFER_USAGE_CPU_WRITE ); + if(surface) { + uint32_t *map; + map = (uint32_t *) pipe_surface_map(surface, PIPE_BUFFER_USAGE_CPU_WRITE ); + if(map) { + *map = 0x00000000; + pipe_surface_unmap( surface ); + } + pipe_surface_reference(&surface, NULL); + } + } + + for (i = 0; i < PIPE_MAX_SAMPLERS; i++) + pipe_texture_reference(&st_ctx->sampler_textures[i], st_ctx->default_texture); + + cso_set_sampler_textures(st_ctx->cso, PIPE_MAX_SAMPLERS, st_ctx->sampler_textures); + } + + /* vertex shader */ + { + struct pipe_shader_state vert_shader; + + const uint semantic_names[] = { TGSI_SEMANTIC_POSITION, + TGSI_SEMANTIC_GENERIC }; + const uint semantic_indexes[] = { 0, 0 }; + st_ctx->vs = util_make_vertex_passthrough_shader(st_ctx->pipe, + 2, + semantic_names, + semantic_indexes, + &vert_shader); + cso_set_vertex_shader_handle(st_ctx->cso, st_ctx->vs); + } + + /* fragment shader */ + { + struct pipe_shader_state frag_shader; + st_ctx->fs = util_make_fragment_passthrough_shader(st_ctx->pipe, + &frag_shader); + cso_set_fragment_shader_handle(st_ctx->cso, st_ctx->fs); + } + + return st_ctx; +} + + +void +st_buffer_destroy(struct st_buffer *st_buf) +{ + if(st_buf) { + struct pipe_screen *screen = st_buf->st_dev->screen; + pipe_buffer_reference(screen, &st_buf->buffer, NULL); + FREE(st_buf); + } +} + + +struct st_buffer * +st_buffer_create(struct st_device *st_dev, + unsigned alignment, unsigned usage, unsigned size) +{ + struct pipe_screen *screen = st_dev->screen; + struct st_buffer *st_buf; + + st_buf = CALLOC_STRUCT(st_buffer); + if(!st_buf) + return NULL; + + st_buf->st_dev = st_dev; + + st_buf->buffer = pipe_buffer_create(screen, alignment, usage, size); + if(!st_buf->buffer) { + st_buffer_destroy(st_buf); + return NULL; + } + + return st_buf; +} + diff --git a/src/gallium/state_trackers/python/st_device.h b/src/gallium/state_trackers/python/st_device.h new file mode 100644 index 00000000000..7cfe6de9f6a --- /dev/null +++ b/src/gallium/state_trackers/python/st_device.h @@ -0,0 +1,101 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#ifndef ST_DEVICE_H_ +#define ST_DEVICE_H_ + + +#include "pipe/p_state.h" + +struct cso_context; +struct pipe_screen; +struct pipe_context; +struct st_winsys; + + +struct st_buffer { + struct st_device *st_dev; + + struct pipe_buffer *buffer; +}; + + +struct st_context { + struct st_device *st_dev; + + struct pipe_context *real_pipe; + struct pipe_context *pipe; + + struct cso_context *cso; + + void *vs; + void *fs; + + struct pipe_texture *default_texture; + struct pipe_texture *sampler_textures[PIPE_MAX_SAMPLERS]; + + unsigned num_vertex_buffers; + struct pipe_vertex_buffer vertex_buffers[PIPE_MAX_ATTRIBS]; + + unsigned num_vertex_elements; + struct pipe_vertex_element vertex_elements[PIPE_MAX_ATTRIBS]; +}; + + +struct st_device { + const struct st_winsys *st_ws; + + struct pipe_screen *real_screen; + struct pipe_screen *screen; + + /* FIXME: we also need to refcount for textures and surfaces... */ + unsigned refcount; +}; + + +struct st_buffer * +st_buffer_create(struct st_device *st_dev, + unsigned alignment, unsigned usage, unsigned size); + +void +st_buffer_destroy(struct st_buffer *st_buf); + +struct st_context * +st_context_create(struct st_device *st_dev); + +void +st_context_destroy(struct st_context *st_ctx); + +struct st_device * +st_device_create(boolean hardware); + +void +st_device_destroy(struct st_device *st_dev); + + +#endif /* ST_DEVICE_H_ */ diff --git a/src/gallium/state_trackers/python/st_hardpipe_winsys.c b/src/gallium/state_trackers/python/st_hardpipe_winsys.c new file mode 100644 index 00000000000..8b33c70fd71 --- /dev/null +++ b/src/gallium/state_trackers/python/st_hardpipe_winsys.c @@ -0,0 +1,62 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Bismarck, ND., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +/** + * @file + * Stub for hardware pipe driver support. + */ + + +#include "pipe/p_compiler.h" + +#include "st_winsys.h" + + +/* XXX: Force init_gallium symbol to be linked */ +extern void init_gallium(void); +void (*force_init_gallium_linkage)(void) = &init_gallium; + + +static struct pipe_screen * +st_hardpipe_screen_create(void) +{ + return st_softpipe_winsys.screen_create(); +} + + +static struct pipe_context * +st_hardpipe_context_create(struct pipe_screen *screen) +{ + return st_softpipe_winsys.context_create(screen); +} + + +const struct st_winsys st_hardpipe_winsys = { + &st_hardpipe_screen_create, + &st_hardpipe_context_create +}; diff --git a/src/gallium/state_trackers/python/st_sample.c b/src/gallium/state_trackers/python/st_sample.c new file mode 100644 index 00000000000..7765df3c4a4 --- /dev/null +++ b/src/gallium/state_trackers/python/st_sample.c @@ -0,0 +1,549 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#include "pipe/p_compiler.h" +#include "pipe/p_format.h" +#include "pipe/p_state.h" +#include "pipe/p_inlines.h" +#include "util/u_tile.h" +#include "util/u_math.h" +#include "util/u_memory.h" + +#include "st_sample.h" + + +/** + * Use our own pseudo random generator to ensure consistent runs among + * multiple runs and platforms. + * + * @sa http://en.wikipedia.org/wiki/Linear_congruential_generator + */ +static uint32_t st_random(void) { + static uint64_t seed = UINT64_C(0xbb9a063afb0a739d); + + seed = UINT64_C(134775813) * seed + UINT64_C(1); + + return (uint16_t)(seed >> 32); +} + + +/** + * We don't want to include the patent-encumbered DXT code here, so instead + * we store several uncompressed/compressed data pairs for hardware testing + * purposes. + */ +struct dxt_data +{ + uint8_t rgba[16*4]; + uint8_t raw[16]; +}; + + +static const struct dxt_data +dxt1_rgb_data[] = { + { + { + 0x99, 0xb0, 0x8e, 0xff, + 0x5d, 0x62, 0x89, 0xff, + 0x99, 0xb0, 0x8e, 0xff, + 0x99, 0xb0, 0x8e, 0xff, + 0xd6, 0xff, 0x94, 0xff, + 0x5d, 0x62, 0x89, 0xff, + 0x99, 0xb0, 0x8e, 0xff, + 0xd6, 0xff, 0x94, 0xff, + 0x5d, 0x62, 0x89, 0xff, + 0x5d, 0x62, 0x89, 0xff, + 0x99, 0xb0, 0x8e, 0xff, + 0x21, 0x14, 0x84, 0xff, + 0x5d, 0x62, 0x89, 0xff, + 0x21, 0x14, 0x84, 0xff, + 0x21, 0x14, 0x84, 0xff, + 0x99, 0xb0, 0x8e, 0xff + }, + {0xf2, 0xd7, 0xb0, 0x20, 0xae, 0x2c, 0x6f, 0x97} + }, + { + { + 0xb5, 0xcf, 0x9c, 0xff, + 0x83, 0x8c, 0x8b, 0xff, + 0x21, 0x08, 0x6b, 0xff, + 0x83, 0x8c, 0x8b, 0xff, + 0x52, 0x4a, 0x7b, 0xff, + 0x83, 0x8c, 0x8b, 0xff, + 0x83, 0x8c, 0x8b, 0xff, + 0xb5, 0xcf, 0x9c, 0xff, + 0x21, 0x08, 0x6b, 0xff, + 0xb5, 0xcf, 0x9c, 0xff, + 0x83, 0x8c, 0x8b, 0xff, + 0x52, 0x4a, 0x7b, 0xff, + 0xb5, 0xcf, 0x9c, 0xff, + 0x83, 0x8c, 0x8b, 0xff, + 0x52, 0x4a, 0x7b, 0xff, + 0x83, 0x8c, 0x8b, 0xff + }, + {0x73, 0xb6, 0x4d, 0x20, 0x98, 0x2b, 0xe1, 0xb8} + }, + { + { + 0x00, 0x2c, 0xff, 0xff, + 0x94, 0x8d, 0x7b, 0xff, + 0x4a, 0x5c, 0xbd, 0xff, + 0x4a, 0x5c, 0xbd, 0xff, + 0x4a, 0x5c, 0xbd, 0xff, + 0x94, 0x8d, 0x7b, 0xff, + 0x94, 0x8d, 0x7b, 0xff, + 0x94, 0x8d, 0x7b, 0xff, + 0xde, 0xbe, 0x39, 0xff, + 0x94, 0x8d, 0x7b, 0xff, + 0xde, 0xbe, 0x39, 0xff, + 0xde, 0xbe, 0x39, 0xff, + 0xde, 0xbe, 0x39, 0xff, + 0xde, 0xbe, 0x39, 0xff, + 0xde, 0xbe, 0x39, 0xff, + 0x94, 0x8d, 0x7b, 0xff + }, + {0xe7, 0xdd, 0x7f, 0x01, 0xf9, 0xab, 0x08, 0x80} + }, + { + { + 0x6b, 0x24, 0x21, 0xff, + 0x7b, 0x4f, 0x5d, 0xff, + 0x7b, 0x4f, 0x5d, 0xff, + 0x8b, 0x7a, 0x99, 0xff, + 0x7b, 0x4f, 0x5d, 0xff, + 0x7b, 0x4f, 0x5d, 0xff, + 0x6b, 0x24, 0x21, 0xff, + 0x8b, 0x7a, 0x99, 0xff, + 0x9c, 0xa6, 0xd6, 0xff, + 0x6b, 0x24, 0x21, 0xff, + 0x7b, 0x4f, 0x5d, 0xff, + 0x8b, 0x7a, 0x99, 0xff, + 0x6b, 0x24, 0x21, 0xff, + 0x8b, 0x7a, 0x99, 0xff, + 0x7b, 0x4f, 0x5d, 0xff, + 0x9c, 0xa6, 0xd6, 0xff + }, + {0x3a, 0x9d, 0x24, 0x69, 0xbd, 0x9f, 0xb4, 0x39} + } +}; + + +static const struct dxt_data +dxt1_rgba_data[] = { + { + { + 0x00, 0x00, 0x00, 0x00, + 0x4e, 0xaa, 0x90, 0xff, + 0x4e, 0xaa, 0x90, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x4e, 0xaa, 0x90, 0xff, + 0x29, 0xff, 0xff, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x4e, 0xaa, 0x90, 0xff, + 0x73, 0x55, 0x21, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x4e, 0xaa, 0x90, 0xff, + 0x4e, 0xaa, 0x90, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x4e, 0xaa, 0x90, 0xff + }, + {0xff, 0x2f, 0xa4, 0x72, 0xeb, 0xb2, 0xbd, 0xbe} + }, + { + { + 0xb5, 0xe3, 0x63, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x6b, 0x24, 0x84, 0xff, + 0xb5, 0xe3, 0x63, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0xb5, 0xe3, 0x63, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x6b, 0x24, 0x84, 0xff, + 0x6b, 0x24, 0x84, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0xb5, 0xe3, 0x63, 0xff, + 0x90, 0x83, 0x73, 0xff, + 0xb5, 0xe3, 0x63, 0xff + }, + {0x30, 0x69, 0x0c, 0xb7, 0x4d, 0xf7, 0x0f, 0x67} + }, + { + { + 0x00, 0x00, 0x00, 0x00, + 0xc6, 0x86, 0x8c, 0xff, + 0xc6, 0x86, 0x8c, 0xff, + 0x21, 0x65, 0x42, 0xff, + 0x21, 0x65, 0x42, 0xff, + 0x21, 0x65, 0x42, 0xff, + 0x21, 0x65, 0x42, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x21, 0x65, 0x42, 0xff, + 0xc6, 0x86, 0x8c, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xc6, 0x86, 0x8c, 0xff + }, + {0x28, 0x23, 0x31, 0xc4, 0x17, 0xc0, 0xd3, 0x7f} + }, + { + { + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0xc6, 0xe3, 0x9c, 0xff, + 0x7b, 0x1c, 0x52, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, + 0x7b, 0x1c, 0x52, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0x7b, 0x1c, 0x52, 0xff, + 0xa0, 0x7f, 0x77, 0xff, + 0xc6, 0xe3, 0x9c, 0xff, + 0x00, 0x00, 0x00, 0x00, + 0xa0, 0x7f, 0x77, 0xff + }, + {0xea, 0x78, 0x13, 0xc7, 0x7f, 0xfc, 0x33, 0xb6} + }, +}; + + +static const struct dxt_data +dxt3_rgba_data[] = { + { + { + 0x6d, 0xc6, 0x96, 0x77, + 0x6d, 0xc6, 0x96, 0xee, + 0x6d, 0xc6, 0x96, 0xaa, + 0x8c, 0xff, 0xb5, 0x44, + 0x6d, 0xc6, 0x96, 0xff, + 0x6d, 0xc6, 0x96, 0x88, + 0x31, 0x55, 0x5a, 0x66, + 0x6d, 0xc6, 0x96, 0x99, + 0x31, 0x55, 0x5a, 0xbb, + 0x31, 0x55, 0x5a, 0x55, + 0x31, 0x55, 0x5a, 0x11, + 0x6d, 0xc6, 0x96, 0xcc, + 0x6d, 0xc6, 0x96, 0xcc, + 0x6d, 0xc6, 0x96, 0x11, + 0x31, 0x55, 0x5a, 0x44, + 0x31, 0x55, 0x5a, 0x88 + }, + {0xe7, 0x4a, 0x8f, 0x96, 0x5b, 0xc1, 0x1c, 0x84, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a} + }, + { + { + 0xad, 0xeb, 0x73, 0x99, + 0x97, 0xaa, 0x86, 0x66, + 0x6b, 0x28, 0xad, 0x99, + 0xad, 0xeb, 0x73, 0x99, + 0x6b, 0x28, 0xad, 0x22, + 0xad, 0xeb, 0x73, 0xff, + 0x97, 0xaa, 0x86, 0x55, + 0x6b, 0x28, 0xad, 0x55, + 0x6b, 0x28, 0xad, 0x44, + 0xad, 0xeb, 0x73, 0x33, + 0x6b, 0x28, 0xad, 0xee, + 0x6b, 0x28, 0xad, 0x99, + 0x97, 0xaa, 0x86, 0x66, + 0xad, 0xeb, 0x73, 0xbb, + 0x97, 0xaa, 0x86, 0x99, + 0xad, 0xeb, 0x73, 0xbb + }, + {0x69, 0x99, 0xf2, 0x55, 0x34, 0x9e, 0xb6, 0xb9, 0x4e, 0xaf, 0x55, 0x69, 0x18, 0x61, 0x51, 0x22} + }, + { + { + 0x63, 0xd7, 0xd6, 0x00, + 0x57, 0x62, 0x5d, 0xdd, + 0x57, 0x62, 0x5d, 0xcc, + 0x57, 0x62, 0x5d, 0xbb, + 0x52, 0x28, 0x21, 0xaa, + 0x57, 0x62, 0x5d, 0xcc, + 0x57, 0x62, 0x5d, 0xcc, + 0x57, 0x62, 0x5d, 0x66, + 0x57, 0x62, 0x5d, 0x22, + 0x57, 0x62, 0x5d, 0xdd, + 0x63, 0xd7, 0xd6, 0xee, + 0x57, 0x62, 0x5d, 0x33, + 0x63, 0xd7, 0xd6, 0x55, + 0x52, 0x28, 0x21, 0x55, + 0x57, 0x62, 0x5d, 0x11, + 0x5d, 0x9c, 0x99, 0xee + }, + {0xd0, 0xbc, 0xca, 0x6c, 0xd2, 0x3e, 0x55, 0xe1, 0xba, 0x66, 0x44, 0x51, 0xfc, 0xfd, 0xcf, 0xb4} + }, + { + { + 0x94, 0x6f, 0x60, 0x22, + 0x94, 0x6f, 0x60, 0x22, + 0xc5, 0xab, 0x76, 0x11, + 0xc5, 0xab, 0x76, 0xee, + 0x63, 0x34, 0x4a, 0xdd, + 0x63, 0x34, 0x4a, 0x33, + 0x94, 0x6f, 0x60, 0x77, + 0xf7, 0xe7, 0x8c, 0x00, + 0x94, 0x6f, 0x60, 0x33, + 0x63, 0x34, 0x4a, 0xaa, + 0x94, 0x6f, 0x60, 0x77, + 0x63, 0x34, 0x4a, 0xcc, + 0x94, 0x6f, 0x60, 0xaa, + 0xf7, 0xe7, 0x8c, 0x99, + 0x63, 0x34, 0x4a, 0x44, + 0xc5, 0xab, 0x76, 0xaa + }, + {0x22, 0xe1, 0x3d, 0x07, 0xa3, 0xc7, 0x9a, 0xa4, 0x31, 0xf7, 0xa9, 0x61, 0xaf, 0x35, 0x77, 0x93} + }, +}; + + +static const struct dxt_data +dxt5_rgba_data[] = { + { + { + 0x6d, 0xc6, 0x96, 0x74, + 0x6d, 0xc6, 0x96, 0xf8, + 0x6d, 0xc6, 0x96, 0xb6, + 0x8c, 0xff, 0xb5, 0x53, + 0x6d, 0xc6, 0x96, 0xf8, + 0x6d, 0xc6, 0x96, 0x95, + 0x31, 0x55, 0x5a, 0x53, + 0x6d, 0xc6, 0x96, 0x95, + 0x31, 0x55, 0x5a, 0xb6, + 0x31, 0x55, 0x5a, 0x53, + 0x31, 0x55, 0x5a, 0x11, + 0x6d, 0xc6, 0x96, 0xd7, + 0x6d, 0xc6, 0x96, 0xb6, + 0x6d, 0xc6, 0x96, 0x11, + 0x31, 0x55, 0x5a, 0x32, + 0x31, 0x55, 0x5a, 0x95 + }, + {0xf8, 0x11, 0xc5, 0x0c, 0x9a, 0x73, 0xb4, 0x9c, 0xf6, 0x8f, 0xab, 0x32, 0x2a, 0x9a, 0x95, 0x5a} + }, + { + { + 0xad, 0xeb, 0x73, 0xa1, + 0x97, 0xaa, 0x86, 0x65, + 0x6b, 0x28, 0xad, 0xa1, + 0xad, 0xeb, 0x73, 0xa1, + 0x6b, 0x28, 0xad, 0x2a, + 0xad, 0xeb, 0x73, 0xfb, + 0x97, 0xaa, 0x86, 0x47, + 0x6b, 0x28, 0xad, 0x65, + 0x6b, 0x28, 0xad, 0x47, + 0xad, 0xeb, 0x73, 0x47, + 0x6b, 0x28, 0xad, 0xdd, + 0x6b, 0x28, 0xad, 0xa1, + 0x97, 0xaa, 0x86, 0x65, + 0xad, 0xeb, 0x73, 0xbf, + 0x97, 0xaa, 0x86, 0xa1, + 0xad, 0xeb, 0x73, 0xbf + }, + {0xfb, 0x2a, 0x34, 0x19, 0xdc, 0xbf, 0xe8, 0x71, 0x4e, 0xaf, 0x55, 0x69, 0x18, 0x61, 0x51, 0x22} + }, + { + { + 0x63, 0xd7, 0xd6, 0x00, + 0x57, 0x62, 0x5d, 0xf5, + 0x57, 0x62, 0x5d, 0xd2, + 0x57, 0x62, 0x5d, 0xaf, + 0x52, 0x28, 0x21, 0xaf, + 0x57, 0x62, 0x5d, 0xd2, + 0x57, 0x62, 0x5d, 0xd2, + 0x57, 0x62, 0x5d, 0x69, + 0x57, 0x62, 0x5d, 0x23, + 0x57, 0x62, 0x5d, 0xd2, + 0x63, 0xd7, 0xd6, 0xf5, + 0x57, 0x62, 0x5d, 0x46, + 0x63, 0xd7, 0xd6, 0x46, + 0x52, 0x28, 0x21, 0x69, + 0x57, 0x62, 0x5d, 0x23, + 0x5d, 0x9c, 0x99, 0xf5 + }, + {0xf5, 0x00, 0x81, 0x36, 0xa9, 0x17, 0xec, 0x1e, 0xba, 0x66, 0x44, 0x51, 0xfc, 0xfd, 0xcf, 0xb4} + }, + { + { + 0x94, 0x6f, 0x60, 0x25, + 0x94, 0x6f, 0x60, 0x25, + 0xc5, 0xab, 0x76, 0x05, + 0xc5, 0xab, 0x76, 0xe8, + 0x63, 0x34, 0x4a, 0xe8, + 0x63, 0x34, 0x4a, 0x25, + 0x94, 0x6f, 0x60, 0x86, + 0xf7, 0xe7, 0x8c, 0x05, + 0x94, 0x6f, 0x60, 0x25, + 0x63, 0x34, 0x4a, 0xa7, + 0x94, 0x6f, 0x60, 0x66, + 0x63, 0x34, 0x4a, 0xc7, + 0x94, 0x6f, 0x60, 0xa7, + 0xf7, 0xe7, 0x8c, 0xa7, + 0x63, 0x34, 0x4a, 0x45, + 0xc5, 0xab, 0x76, 0xa7 + }, + {0xe8, 0x05, 0x7f, 0x80, 0x33, 0x5f, 0xb5, 0x79, 0x31, 0xf7, 0xa9, 0x61, 0xaf, 0x35, 0x77, 0x93} + }, +}; + + +static INLINE void +st_sample_dxt_pixel_block(enum pipe_format format, + const struct pipe_format_block *block, + uint8_t *raw, + float *rgba, unsigned rgba_stride, + unsigned w, unsigned h) +{ + const struct dxt_data *data; + unsigned n; + unsigned i; + unsigned x, y, ch; + + switch(format) { + case PIPE_FORMAT_DXT1_RGB: + data = dxt1_rgb_data; + n = sizeof(dxt1_rgb_data)/sizeof(dxt1_rgb_data[0]); + break; + case PIPE_FORMAT_DXT1_RGBA: + data = dxt1_rgba_data; + n = sizeof(dxt1_rgba_data)/sizeof(dxt1_rgba_data[0]); + break; + case PIPE_FORMAT_DXT3_RGBA: + data = dxt3_rgba_data; + n = sizeof(dxt3_rgba_data)/sizeof(dxt3_rgba_data[0]); + break; + case PIPE_FORMAT_DXT5_RGBA: + data = dxt5_rgba_data; + n = sizeof(dxt5_rgba_data)/sizeof(dxt5_rgba_data[0]); + break; + default: + assert(0); + } + + i = st_random() % n; + + for(y = 0; y < h; ++y) + for(x = 0; x < w; ++x) + for(ch = 0; ch < 4; ++ch) + rgba[y*rgba_stride + x*4 + ch] = (float)(data[i].rgba[y*4*4 + x*4 + ch])/255.0f; + + memcpy(raw, data[i].raw, block->size); +} + + +static INLINE void +st_sample_generic_pixel_block(enum pipe_format format, + const struct pipe_format_block *block, + uint8_t *raw, + float *rgba, unsigned rgba_stride, + unsigned w, unsigned h) +{ + unsigned i; + unsigned x, y, ch; + + for(i = 0; i < block->size; ++i) + raw[i] = (uint8_t)st_random(); + + + pipe_tile_raw_to_rgba(format, + raw, + w, h, + rgba, rgba_stride); + + if(format == PIPE_FORMAT_YCBCR || format == PIPE_FORMAT_YCBCR_REV) { + for(y = 0; y < h; ++y) { + for(x = 0; x < w; ++x) { + for(ch = 0; ch < 4; ++ch) { + unsigned offset = y*rgba_stride + x*4 + ch; + rgba[offset] = CLAMP(rgba[offset], 0.0f, 1.0f); + } + } + } + } +} + + +/** + * Randomly sample pixels. + */ +void +st_sample_pixel_block(enum pipe_format format, + const struct pipe_format_block *block, + void *raw, + float *rgba, unsigned rgba_stride, + unsigned w, unsigned h) +{ + switch(format) { + case PIPE_FORMAT_DXT1_RGB: + case PIPE_FORMAT_DXT1_RGBA: + case PIPE_FORMAT_DXT3_RGBA: + case PIPE_FORMAT_DXT5_RGBA: + st_sample_dxt_pixel_block(format, block, raw, rgba, rgba_stride, w, h); + break; + + default: + st_sample_generic_pixel_block(format, block, raw, rgba, rgba_stride, w, h); + break; + } +} + + +void +st_sample_surface(struct pipe_surface *surface, float *rgba) +{ + const struct pipe_format_block *block = &surface->block; + unsigned rgba_stride = surface->width*4; + void *raw; + unsigned x, y; + + raw = pipe_surface_map(surface, PIPE_BUFFER_USAGE_CPU_READ); + if(!raw) + return; + + for (y = 0; y < surface->nblocksy; ++y) { + for(x = 0; x < surface->nblocksx; ++x) { + st_sample_pixel_block(surface->format, + block, + (uint8_t*)raw + y*surface->stride + x*block->size, + rgba + y*block->height*rgba_stride + x*block->width*4, + rgba_stride, + MIN2(block->width, surface->width - x*block->width), + MIN2(block->height, surface->height - y*block->height)); + } + } + + pipe_surface_unmap(surface); +} diff --git a/src/gallium/state_trackers/python/st_sample.h b/src/gallium/state_trackers/python/st_sample.h new file mode 100644 index 00000000000..ff04a12613f --- /dev/null +++ b/src/gallium/state_trackers/python/st_sample.h @@ -0,0 +1,47 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#ifndef ST_SAMPLE_H_ +#define ST_SAMPLE_H_ + + +#include "pipe/p_format.h" + + +void +st_sample_pixel_block(enum pipe_format format, + const struct pipe_format_block *block, + void *raw, + float *rgba, unsigned rgba_stride, + unsigned w, unsigned h); + +void +st_sample_surface(struct pipe_surface *surface, float *rgba); + + +#endif /* ST_SAMPLE_H_ */ diff --git a/src/gallium/state_trackers/python/st_softpipe_winsys.c b/src/gallium/state_trackers/python/st_softpipe_winsys.c new file mode 100644 index 00000000000..4d798df99bf --- /dev/null +++ b/src/gallium/state_trackers/python/st_softpipe_winsys.c @@ -0,0 +1,271 @@ +/************************************************************************** + * + * Copyright 2007 Tungsten Graphics, Inc., Bismarck, ND., USA + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. IN NO EVENT SHALL + * THE COPYRIGHT HOLDERS, AUTHORS AND/OR ITS SUPPLIERS BE LIABLE FOR ANY CLAIM, + * DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR + * OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE + * USE OR OTHER DEALINGS IN THE SOFTWARE. + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * + **************************************************************************/ + +/** + * @file + * Softpipe support. + * + * @author Keith Whitwell + * @author Brian Paul + * @author Jose Fonseca + */ + + +#include "pipe/internal/p_winsys_screen.h"/* port to just p_screen */ +#include "pipe/p_format.h" +#include "pipe/p_context.h" +#include "pipe/p_inlines.h" +#include "util/u_math.h" +#include "util/u_memory.h" +#include "softpipe/sp_winsys.h" +#include "st_winsys.h" + + +struct st_softpipe_buffer +{ + struct pipe_buffer base; + boolean userBuffer; /** Is this a user-space buffer? */ + void *data; + void *mapped; +}; + + +/** Cast wrapper */ +static INLINE struct st_softpipe_buffer * +st_softpipe_buffer( struct pipe_buffer *buf ) +{ + return (struct st_softpipe_buffer *)buf; +} + + +static void * +st_softpipe_buffer_map(struct pipe_winsys *winsys, + struct pipe_buffer *buf, + unsigned flags) +{ + struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); + st_softpipe_buf->mapped = st_softpipe_buf->data; + return st_softpipe_buf->mapped; +} + + +static void +st_softpipe_buffer_unmap(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + struct st_softpipe_buffer *st_softpipe_buf = st_softpipe_buffer(buf); + st_softpipe_buf->mapped = NULL; +} + + +static void +st_softpipe_buffer_destroy(struct pipe_winsys *winsys, + struct pipe_buffer *buf) +{ + struct st_softpipe_buffer *oldBuf = st_softpipe_buffer(buf); + + if (oldBuf->data) { + if (!oldBuf->userBuffer) + align_free(oldBuf->data); + + oldBuf->data = NULL; + } + + FREE(oldBuf); +} + + +static void +st_softpipe_flush_frontbuffer(struct pipe_winsys *winsys, + struct pipe_surface *surf, + void *context_private) +{ +} + + + +static const char * +st_softpipe_get_name(struct pipe_winsys *winsys) +{ + return "softpipe"; +} + + +static struct pipe_buffer * +st_softpipe_buffer_create(struct pipe_winsys *winsys, + unsigned alignment, + unsigned usage, + unsigned size) +{ + struct st_softpipe_buffer *buffer = CALLOC_STRUCT(st_softpipe_buffer); + + buffer->base.refcount = 1; + buffer->base.alignment = alignment; + buffer->base.usage = usage; + buffer->base.size = size; + + buffer->data = align_malloc(size, alignment); + + return &buffer->base; +} + + +/** + * Create buffer which wraps user-space data. + */ +static struct pipe_buffer * +st_softpipe_user_buffer_create(struct pipe_winsys *winsys, + void *ptr, + unsigned bytes) +{ + struct st_softpipe_buffer *buffer; + + buffer = CALLOC_STRUCT(st_softpipe_buffer); + if(!buffer) + return NULL; + + buffer->base.refcount = 1; + buffer->base.size = bytes; + buffer->userBuffer = TRUE; + buffer->data = ptr; + + return &buffer->base; +} + + +/** + * Round n up to next multiple. + */ +static INLINE unsigned +round_up(unsigned n, unsigned multiple) +{ + return (n + multiple - 1) & ~(multiple - 1); +} + + +static struct pipe_buffer * +st_softpipe_surface_buffer_create(struct pipe_winsys *winsys, + unsigned width, unsigned height, + enum pipe_format format, + unsigned usage, + unsigned *stride) +{ + const unsigned alignment = 64; + struct pipe_format_block block; + unsigned nblocksx, nblocksy; + + pf_get_block(format, &block); + nblocksx = pf_get_nblocksx(&block, width); + nblocksy = pf_get_nblocksy(&block, height); + *stride = round_up(nblocksx * block.size, alignment); + + return winsys->buffer_create(winsys, alignment, + usage, + *stride * nblocksy); +} + + +static void +st_softpipe_fence_reference(struct pipe_winsys *winsys, + struct pipe_fence_handle **ptr, + struct pipe_fence_handle *fence) +{ +} + + +static int +st_softpipe_fence_signalled(struct pipe_winsys *winsys, + struct pipe_fence_handle *fence, + unsigned flag) +{ + return 0; +} + + +static int +st_softpipe_fence_finish(struct pipe_winsys *winsys, + struct pipe_fence_handle *fence, + unsigned flag) +{ + return 0; +} + + +static void +st_softpipe_destroy(struct pipe_winsys *winsys) +{ + FREE(winsys); +} + + +static struct pipe_screen * +st_softpipe_screen_create(void) +{ + static struct pipe_winsys *winsys; + struct pipe_screen *screen; + + winsys = CALLOC_STRUCT(pipe_winsys); + if(!winsys) + return NULL; + + winsys->destroy = st_softpipe_destroy; + + winsys->buffer_create = st_softpipe_buffer_create; + winsys->user_buffer_create = st_softpipe_user_buffer_create; + winsys->buffer_map = st_softpipe_buffer_map; + winsys->buffer_unmap = st_softpipe_buffer_unmap; + winsys->buffer_destroy = st_softpipe_buffer_destroy; + + winsys->surface_buffer_create = st_softpipe_surface_buffer_create; + + winsys->fence_reference = st_softpipe_fence_reference; + winsys->fence_signalled = st_softpipe_fence_signalled; + winsys->fence_finish = st_softpipe_fence_finish; + + winsys->flush_frontbuffer = st_softpipe_flush_frontbuffer; + winsys->get_name = st_softpipe_get_name; + + screen = softpipe_create_screen(winsys); + if(!screen) + st_softpipe_destroy(winsys); + + return screen; +} + + +static struct pipe_context * +st_softpipe_context_create(struct pipe_screen *screen) +{ + return softpipe_create(screen, screen->winsys, NULL); +} + + +const struct st_winsys st_softpipe_winsys = { + &st_softpipe_screen_create, + &st_softpipe_context_create, +}; diff --git a/src/gallium/state_trackers/python/st_winsys.h b/src/gallium/state_trackers/python/st_winsys.h new file mode 100644 index 00000000000..b8cb612d863 --- /dev/null +++ b/src/gallium/state_trackers/python/st_winsys.h @@ -0,0 +1,52 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + + +#ifndef ST_WINSYS_H_ +#define ST_WINSYS_H_ + + +struct pipe_screen; +struct pipe_context; + + +struct st_winsys +{ + struct pipe_screen * + (*screen_create)(void); + + struct pipe_context * + (*context_create)(struct pipe_screen *screen); +}; + + +extern const struct st_winsys st_softpipe_winsys; + +extern const struct st_winsys st_hardpipe_winsys; + + +#endif /* ST_WINSYS_H_ */ diff --git a/src/gallium/state_trackers/python/tests/base.py b/src/gallium/state_trackers/python/tests/base.py new file mode 100644 index 00000000000..8477aa5fc9b --- /dev/null +++ b/src/gallium/state_trackers/python/tests/base.py @@ -0,0 +1,193 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial portions +# of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +########################################################################## + + +"""Base classes for tests. + +Loosely inspired on Python's unittest module. +""" + + +from gallium import * + + +# Enumerate all pixel formats +formats = {} +for name, value in globals().items(): + if name.startswith("PIPE_FORMAT_") and isinstance(value, int): + formats[value] = name + + +def make_image(width, height, rgba): + import Image + outimage = Image.new( + mode='RGB', + size=(width, height), + color=(0,0,0)) + outpixels = outimage.load() + for y in range(0, height): + for x in range(0, width): + offset = (y*width + x)*4 + r, g, b, a = [int(min(max(rgba[offset + ch], 0.0), 1.0)*255) for ch in range(4)] + outpixels[x, y] = r, g, b + return outimage + +def save_image(width, height, rgba, filename): + outimage = make_image(width, height, rgba) + outimage.save(filename, "PNG") + +def show_image(width, height, **rgbas): + import Tkinter as tk + from PIL import Image, ImageTk + + root = tk.Tk() + + x = 64 + y = 64 + + labels = rgbas.keys() + labels.sort() + for i in range(len(labels)): + label = labels[i] + outimage = make_image(width, height, rgbas[label]) + + if i: + window = tk.Toplevel(root) + else: + window = root + window.title(label) + image1 = ImageTk.PhotoImage(outimage) + w = image1.width() + h = image1.height() + window.geometry("%dx%d+%d+%d" % (w, h, x, y)) + panel1 = tk.Label(window, image=image1) + panel1.pack(side='top', fill='both', expand='yes') + panel1.image = image1 + x += w + 2 + + root.mainloop() + + +class TestFailure(Exception): + + pass + +class TestSkip(Exception): + + pass + + +class Test: + + def __init__(self): + pass + + def _run(self, result): + raise NotImplementedError + + def run(self): + result = TestResult() + self._run(result) + result.summary() + + +class TestCase(Test): + + def __init__(self, dev, **kargs): + Test.__init__(self) + self.dev = dev + self.__dict__.update(kargs) + + def description(self): + raise NotImplementedError + + def test(self): + raise NotImplementedError + + def _run(self, result): + result.test_start(self) + try: + self.test() + except KeyboardInterrupt: + raise + except TestSkip: + result.test_skipped(self) + except TestFailure: + result.test_failed(self) + else: + result.test_passed(self) + + +class TestSuite(Test): + + def __init__(self, tests = None): + Test.__init__(self) + if tests is None: + self.tests = [] + else: + self.tests = tests + + def add_test(self, test): + self.tests.append(test) + + def _run(self, result): + for test in self.tests: + test._run(result) + + +class TestResult: + + def __init__(self): + self.tests = 0 + self.passed = 0 + self.skipped = 0 + self.failed = 0 + self.failed_descriptions = [] + + def test_start(self, test): + self.tests += 1 + print "Running %s..." % test.description() + + def test_passed(self, test): + self.passed += 1 + print "PASS" + + def test_skipped(self, test): + self.skipped += 1 + print "SKIP" + + def test_failed(self, test): + self.failed += 1 + self.failed_descriptions.append(test.description()) + print "FAIL" + + def summary(self): + print "%u tests, %u passed, %u skipped, %u failed" % (self.tests, self.passed, self.skipped, self.failed) + for description in self.failed_descriptions: + print " %s" % description +
\ No newline at end of file diff --git a/src/gallium/state_trackers/python/tests/texture.py b/src/gallium/state_trackers/python/tests/texture.py new file mode 100644 index 00000000000..880a61306c9 --- /dev/null +++ b/src/gallium/state_trackers/python/tests/texture.py @@ -0,0 +1,397 @@ +#!/usr/bin/env python +########################################################################## +# +# Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. +# All Rights Reserved. +# +# Permission is hereby granted, free of charge, to any person obtaining a +# copy of this software and associated documentation files (the +# "Software"), to deal in the Software without restriction, including +# without limitation the rights to use, copy, modify, merge, publish, +# distribute, sub license, and/or sell copies of the Software, and to +# permit persons to whom the Software is furnished to do so, subject to +# the following conditions: +# +# The above copyright notice and this permission notice (including the +# next paragraph) shall be included in all copies or substantial portions +# of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS +# OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF +# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. +# IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR +# ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +# TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +# SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. +# +########################################################################## + + +import sys +from gallium import * +from base import * + + +def lods(*dims): + size = max(dims) + lods = 0 + while size: + lods += 1 + size >>= 1 + return lods + + +def minify(dims, level = 1): + return [max(dim>>level, 1) for dim in dims] + + +def tex_coords(texture, face, level, zslice): + st = [ + [0.0, 0.0], + [1.0, 0.0], + [1.0, 1.0], + [0.0, 1.0], + ] + + if texture.target == PIPE_TEXTURE_2D: + return [[s, t, 0.0] for s, t in st] + elif texture.target == PIPE_TEXTURE_3D: + depth = texture.get_depth(level) + if depth > 1: + r = float(zslice)/float(depth - 1) + else: + r = 0.0 + return [[s, t, r] for s, t in st] + elif texture.target == PIPE_TEXTURE_CUBE: + result = [] + for s, t in st: + # See http://developer.nvidia.com/object/cube_map_ogl_tutorial.html + sc = 2.0*s - 1.0 + tc = 2.0*t - 1.0 + if face == PIPE_TEX_FACE_POS_X: + rx = 1.0 + ry = -tc + rz = -sc + if face == PIPE_TEX_FACE_NEG_X: + rx = -1.0 + ry = -tc + rz = sc + if face == PIPE_TEX_FACE_POS_Y: + rx = sc + ry = 1.0 + rz = tc + if face == PIPE_TEX_FACE_NEG_Y: + rx = sc + ry = -1.0 + rz = -tc + if face == PIPE_TEX_FACE_POS_Z: + rx = sc + ry = -tc + rz = 1.0 + if face == PIPE_TEX_FACE_NEG_Z: + rx = -sc + ry = -tc + rz = -1.0 + result.append([rx, ry, rz]) + return result + +def is_pot(n): + return n & (n - 1) == 0 + + +class TextureTest(TestCase): + + def description(self): + target = { + PIPE_TEXTURE_1D: "1d", + PIPE_TEXTURE_2D: "2d", + PIPE_TEXTURE_3D: "3d", + PIPE_TEXTURE_CUBE: "cube", + }[self.target] + format = formats[self.format] + if self.target == PIPE_TEXTURE_CUBE: + face = { + PIPE_TEX_FACE_POS_X: "+x", + PIPE_TEX_FACE_NEG_X: "-x", + PIPE_TEX_FACE_POS_Y: "+y", + PIPE_TEX_FACE_NEG_Y: "-y", + PIPE_TEX_FACE_POS_Z: "+z", + PIPE_TEX_FACE_NEG_Z: "-z", + }[self.face] + else: + face = "" + return "%s %s %ux%ux%u last_level=%u face=%s level=%u zslice=%u" % ( + target, format, + self.width, self.height, self.depth, self.last_level, + face, self.level, self.zslice, + ) + + def test(self): + dev = self.dev + + target = self.target + format = self.format + width = self.width + height = self.height + depth = self.depth + last_level = self.last_level + face = self.face + level = self.level + zslice = self.zslice + + tex_usage = PIPE_TEXTURE_USAGE_SAMPLER + geom_flags = 0 + if width != height: + geom_flags |= PIPE_TEXTURE_GEOM_NON_SQUARE + if not is_pot(width) or not is_pot(height) or not is_pot(depth): + geom_flags |= PIPE_TEXTURE_GEOM_NON_POWER_OF_TWO + + if not dev.is_format_supported(format, target, tex_usage, geom_flags): + raise TestSkip + + ctx = self.dev.context_create() + + # disabled blending/masking + blend = Blend() + blend.rgb_src_factor = PIPE_BLENDFACTOR_ONE + blend.alpha_src_factor = PIPE_BLENDFACTOR_ONE + blend.rgb_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.alpha_dst_factor = PIPE_BLENDFACTOR_ZERO + blend.colormask = PIPE_MASK_RGBA + ctx.set_blend(blend) + + # no-op depth/stencil/alpha + depth_stencil_alpha = DepthStencilAlpha() + ctx.set_depth_stencil_alpha(depth_stencil_alpha) + + # rasterizer + rasterizer = Rasterizer() + rasterizer.front_winding = PIPE_WINDING_CW + rasterizer.cull_mode = PIPE_WINDING_NONE + rasterizer.bypass_clipping = 1 + #rasterizer.bypass_vs = 1 + ctx.set_rasterizer(rasterizer) + + # viewport (identity, we setup vertices in wincoords) + viewport = Viewport() + scale = FloatArray(4) + scale[0] = 1.0 + scale[1] = 1.0 + scale[2] = 1.0 + scale[3] = 1.0 + viewport.scale = scale + translate = FloatArray(4) + translate[0] = 0.0 + translate[1] = 0.0 + translate[2] = 0.0 + translate[3] = 0.0 + viewport.translate = translate + ctx.set_viewport(viewport) + + # samplers + sampler = Sampler() + sampler.wrap_s = PIPE_TEX_WRAP_CLAMP_TO_EDGE + sampler.wrap_t = PIPE_TEX_WRAP_CLAMP_TO_EDGE + sampler.wrap_r = PIPE_TEX_WRAP_CLAMP_TO_EDGE + sampler.min_mip_filter = PIPE_TEX_MIPFILTER_NEAREST + sampler.min_img_filter = PIPE_TEX_MIPFILTER_NEAREST + sampler.mag_img_filter = PIPE_TEX_MIPFILTER_NEAREST + sampler.normalized_coords = 1 + sampler.min_lod = 0 + sampler.max_lod = PIPE_MAX_TEXTURE_LEVELS - 1 + ctx.set_sampler(0, sampler) + + # texture + texture = dev.texture_create( + target = target, + format = format, + width = width, + height = height, + depth = depth, + last_level = last_level, + tex_usage = tex_usage, + ) + + expected_rgba = FloatArray(height*width*4) + texture.get_surface( + usage = PIPE_BUFFER_USAGE_CPU_READ|PIPE_BUFFER_USAGE_CPU_WRITE, + face = face, + level = level, + zslice = zslice, + ).sample_rgba(expected_rgba) + + ctx.set_sampler_texture(0, texture) + + # framebuffer + cbuf_tex = dev.texture_create( + PIPE_FORMAT_A8R8G8B8_UNORM, + width, + height, + tex_usage = PIPE_TEXTURE_USAGE_RENDER_TARGET, + ) + + cbuf = cbuf_tex.get_surface(usage = PIPE_BUFFER_USAGE_GPU_WRITE|PIPE_BUFFER_USAGE_GPU_READ) + fb = Framebuffer() + fb.width = width + fb.height = height + fb.num_cbufs = 1 + fb.set_cbuf(0, cbuf) + ctx.set_framebuffer(fb) + ctx.surface_clear(cbuf, 0x00000000) + del fb + + # vertex shader + vs = Shader(''' + VERT1.1 + DCL IN[0], POSITION, CONSTANT + DCL IN[1], GENERIC, CONSTANT + DCL OUT[0], POSITION, CONSTANT + DCL OUT[1], GENERIC, CONSTANT + 0:MOV OUT[0], IN[0] + 1:MOV OUT[1], IN[1] + 2:END + ''') + #vs.dump() + ctx.set_vertex_shader(vs) + + # fragment shader + op = { + PIPE_TEXTURE_1D: "1D", + PIPE_TEXTURE_2D: "2D", + PIPE_TEXTURE_3D: "3D", + PIPE_TEXTURE_CUBE: "CUBE", + }[target] + fs = Shader(''' + FRAG1.1 + DCL IN[0], GENERIC[0], LINEAR + DCL OUT[0], COLOR, CONSTANT + DCL SAMP[0], CONSTANT + 0:TEX OUT[0], IN[0], SAMP[0], %s + 1:END + ''' % op) + #fs.dump() + ctx.set_fragment_shader(fs) + + nverts = 4 + nattrs = 2 + verts = FloatArray(nverts * nattrs * 4) + + x = 0 + y = 0 + w, h = minify((width, height), level) + + pos = [ + [x, y], + [x+w, y], + [x+w, y+h], + [x, y+h], + ] + + tex = tex_coords(texture, face, level, zslice) + + for i in range(0, 4): + j = 8*i + verts[j + 0] = pos[i][0] # x + verts[j + 1] = pos[i][1] # y + verts[j + 2] = 0.0 # z + verts[j + 3] = 1.0 # w + verts[j + 4] = tex[i][0] # s + verts[j + 5] = tex[i][1] # r + verts[j + 6] = tex[i][2] # q + verts[j + 7] = 1.0 + + ctx.draw_vertices(PIPE_PRIM_TRIANGLE_FAN, + nverts, + nattrs, + verts) + + ctx.flush() + + cbuf = cbuf_tex.get_surface(usage = PIPE_BUFFER_USAGE_CPU_READ) + + total = h*w + different = cbuf.compare_tile_rgba(x, y, w, h, expected_rgba, tol=4.0/256) + if different: + sys.stderr.write("%u out of %u pixels differ\n" % (different, total)) + + if float(total - different)/float(total) < 0.85: + + if 0: + rgba = FloatArray(h*w*4) + cbuf.get_tile_rgba(x, y, w, h, rgba) + show_image(w, h, Result=rgba, Expected=expected_rgba) + save_image(w, h, rgba, "result.png") + save_image(w, h, expected_rgba, "expected.png") + #sys.exit(0) + + raise TestFailure + + del ctx + + + +def main(): + dev = Device() + suite = TestSuite() + + targets = [] + targets += [PIPE_TEXTURE_2D] + targets += [PIPE_TEXTURE_CUBE] + targets += [PIPE_TEXTURE_3D] + + formats = [] + formats += [PIPE_FORMAT_A8R8G8B8_UNORM] + formats += [PIPE_FORMAT_R5G6B5_UNORM] + formats += [PIPE_FORMAT_L8_UNORM] + formats += [PIPE_FORMAT_YCBCR] + formats += [PIPE_FORMAT_DXT1_RGB] + + sizes = [64, 32, 16, 8, 4, 2, 1] + #sizes = [1020, 508, 252, 62, 30, 14, 6, 3] + #sizes = [64] + #sizes = [63] + + for target in targets: + for format in formats: + for size in sizes: + if target == PIPE_TEXTURE_CUBE: + faces = [ + PIPE_TEX_FACE_POS_X, + PIPE_TEX_FACE_NEG_X, + PIPE_TEX_FACE_POS_Y, + PIPE_TEX_FACE_NEG_Y, + PIPE_TEX_FACE_POS_Z, + PIPE_TEX_FACE_NEG_Z, + ] + #faces = [PIPE_TEX_FACE_NEG_X] + else: + faces = [0] + if target == PIPE_TEXTURE_3D: + depth = size + else: + depth = 1 + for face in faces: + levels = lods(size) + for last_level in range(levels): + for level in range(0, last_level + 1): + zslice = 0 + while zslice < depth >> level: + test = TextureTest( + dev = dev, + target = target, + format = format, + width = size, + height = size, + depth = depth, + last_level = last_level, + face = face, + level = level, + zslice = zslice, + ) + suite.add_test(test) + zslice = (zslice + 1)*2 - 1 + suite.run() + + +if __name__ == '__main__': + main() diff --git a/src/gallium/state_trackers/wgl/SConscript b/src/gallium/state_trackers/wgl/SConscript new file mode 100644 index 00000000000..c72f495735d --- /dev/null +++ b/src/gallium/state_trackers/wgl/SConscript @@ -0,0 +1,43 @@ +import os + +Import('*') + +if env['platform'] in ['windows']: + + env = env.Clone() + + env.Append(CPPPATH = [ + '#src/mesa', + '.', + ]) + + env.Append(CPPDEFINES = [ + '_GDI32_', # prevent wgl* being declared __declspec(dllimport) + 'BUILD_GL32', # declare gl* as __declspec(dllexport) in Mesa headers + '__GL_EXPORTS', + '_GNU_H_WINDOWS32_DEFINES', + ]) + + sources = [ + 'stw.c', + + 'icd/stw_icd.c', + + 'wgl/stw_wgl.c', + + 'shared/stw_context.c', + 'shared/stw_device.c', + 'shared/stw_framebuffer.c', + 'shared/stw_pixelformat.c', + 'shared/stw_quirks.c', + 'shared/stw_arbextensionsstring.c', + 'shared/stw_getprocaddress.c', + 'shared/stw_arbpixelformat.c', + ] + + wgl = env.ConvenienceLibrary( + target ='wgl', + source = sources, + ) + + Export('wgl') diff --git a/src/gallium/state_trackers/wgl/icd/stw_icd.c b/src/gallium/state_trackers/wgl/icd/stw_icd.c new file mode 100644 index 00000000000..1aa4b8a6e22 --- /dev/null +++ b/src/gallium/state_trackers/wgl/icd/stw_icd.c @@ -0,0 +1,773 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <windows.h> +#include <stdio.h> + +#include "GL/gl.h" + +#include "pipe/p_debug.h" +#include "pipe/p_thread.h" + +#include "shared/stw_public.h" +#include "icd/stw_icd.h" +#include "stw.h" + + +#define DRV_CONTEXT_MAX 32 + +struct stw_icd +{ + pipe_mutex mutex; + + GLCLTPROCTABLE cpt; + boolean cpt_initialized; + + struct { + struct stw_context *ctx; + } ctx_array[DRV_CONTEXT_MAX]; +}; + + +static struct stw_icd *stw_icd = NULL; + + +boolean +stw_icd_init( void ) +{ + static struct stw_icd stw_icd_storage; + + assert(!stw_icd); + + stw_icd = &stw_icd_storage; + memset(stw_icd, 0, sizeof *stw_icd); + + pipe_mutex_init( stw_icd->mutex ); + + return TRUE; +} + +void +stw_icd_cleanup(void) +{ + int i; + + if (!stw_icd) + return; + + pipe_mutex_lock( stw_icd->mutex ); + { + /* Ensure all contexts are destroyed */ + for (i = 0; i < DRV_CONTEXT_MAX; i++) + if (stw_icd->ctx_array[i].ctx) + stw_delete_context( stw_icd->ctx_array[i].ctx ); + } + pipe_mutex_unlock( stw_icd->mutex ); + + pipe_mutex_init( stw_icd->mutex ); + stw_icd = NULL; +} + + +static struct stw_context * +lookup_context( struct stw_icd *icd, + DHGLRC dhglrc ) +{ + if (dhglrc == 0 || + dhglrc >= DRV_CONTEXT_MAX) + return NULL; + + if (icd == NULL) + return NULL; + + return icd->ctx_array[dhglrc - 1].ctx; +} + +BOOL APIENTRY +DrvCopyContext( + DHGLRC dhrcSource, + DHGLRC dhrcDest, + UINT fuMask ) +{ + BOOL ret = FALSE; + + if (!stw_icd) + return FALSE; + + pipe_mutex_lock( stw_icd->mutex ); + { + struct stw_context *src = lookup_context( stw_icd, dhrcSource ); + struct stw_context *dst = lookup_context( stw_icd, dhrcDest ); + + if (src == NULL || dst == NULL) + goto done; + + ret = stw_copy_context( src, dst, fuMask ); + } +done: + pipe_mutex_unlock( stw_icd->mutex ); + + return ret; +} + +DHGLRC APIENTRY +DrvCreateLayerContext( + HDC hdc, + INT iLayerPlane ) +{ + DHGLRC handle = 0; + + if (!stw_icd) + return handle; + + pipe_mutex_lock( stw_icd->mutex ); + { + int i; + + for (i = 0; i < DRV_CONTEXT_MAX; i++) { + if (stw_icd->ctx_array[i].ctx == NULL) + break; + } + + /* No slot available, fail: + */ + if (i == DRV_CONTEXT_MAX) + goto done; + + stw_icd->ctx_array[i].ctx = stw_create_context( hdc, iLayerPlane ); + if (stw_icd->ctx_array[i].ctx == NULL) + goto done; + + /* success: + */ + handle = (DHGLRC) i + 1; + } +done: + pipe_mutex_unlock( stw_icd->mutex ); + + return handle; +} + +DHGLRC APIENTRY +DrvCreateContext( + HDC hdc ) +{ + return DrvCreateLayerContext( hdc, 0 ); +} + +BOOL APIENTRY +DrvDeleteContext( + DHGLRC dhglrc ) +{ + BOOL ret = FALSE; + + if (!stw_icd) + return ret; + + pipe_mutex_lock( stw_icd->mutex ); + { + struct stw_context *ctx; + + ctx = lookup_context( stw_icd, dhglrc ); + if (ctx == NULL) + goto done; + + if (stw_delete_context( ctx ) == FALSE) + goto done; + + stw_icd->ctx_array[dhglrc - 1].ctx = NULL; + ret = TRUE; + + } +done: + pipe_mutex_unlock( stw_icd->mutex ); + + return ret; +} + +BOOL APIENTRY +DrvDescribeLayerPlane( + HDC hdc, + INT iPixelFormat, + INT iLayerPlane, + UINT nBytes, + LPLAYERPLANEDESCRIPTOR plpd ) +{ + debug_printf( "%s\n", __FUNCTION__ ); + + return FALSE; +} + +LONG APIENTRY +DrvDescribePixelFormat( + HDC hdc, + INT iPixelFormat, + ULONG cjpfd, + PIXELFORMATDESCRIPTOR *ppfd ) +{ + LONG r; + + r = stw_pixelformat_describe( hdc, iPixelFormat, cjpfd, ppfd ); + + debug_printf( "%s( %p, %d, %u, %p ) = %d\n", + __FUNCTION__, hdc, iPixelFormat, cjpfd, ppfd, r ); + + return r; +} + +int APIENTRY +DrvGetLayerPaletteEntries( + HDC hdc, + INT iLayerPlane, + INT iStart, + INT cEntries, + COLORREF *pcr ) +{ + debug_printf( "%s\n", __FUNCTION__ ); + + return 0; +} + +PROC APIENTRY +DrvGetProcAddress( + LPCSTR lpszProc ) +{ + PROC r; + + r = stw_get_proc_address( lpszProc ); + + debug_printf( "%s( \", __FUNCTION__%s\" ) = %p\n", lpszProc, r ); + + return r; +} + +BOOL APIENTRY +DrvRealizeLayerPalette( + HDC hdc, + INT iLayerPlane, + BOOL bRealize ) +{ + debug_printf( "%s\n", __FUNCTION__ ); + + return FALSE; +} + +BOOL APIENTRY +DrvReleaseContext( + DHGLRC dhglrc ) +{ + BOOL ret = FALSE; + + if (!stw_icd) + return ret; + + pipe_mutex_lock( stw_icd->mutex ); + { + struct stw_context *ctx; + + /* XXX: The expectation is that ctx is the same context which is + * current for this thread. We should check that and return False + * if not the case. + */ + ctx = lookup_context( stw_icd, dhglrc ); + if (ctx == NULL) + goto done; + + if (stw_make_current( NULL, NULL ) == FALSE) + goto done; + + ret = TRUE; + } +done: + pipe_mutex_unlock( stw_icd->mutex ); + + return ret; +} + +void APIENTRY +DrvSetCallbackProcs( + INT nProcs, + PROC *pProcs ) +{ + debug_printf( "%s( %d, %p )\n", __FUNCTION__, nProcs, pProcs ); + + return; +} + + +static void init_proc_table( GLCLTPROCTABLE *cpt ) +{ + GLDISPATCHTABLE *disp = &cpt->glDispatchTable; + + memset( cpt, 0, sizeof *cpt ); + cpt->cEntries = OPENGL_VERSION_110_ENTRIES; + +#define GPA_GL( NAME ) disp->NAME = gl##NAME + GPA_GL( NewList ); + GPA_GL( EndList ); + GPA_GL( CallList ); + GPA_GL( CallLists ); + GPA_GL( DeleteLists ); + GPA_GL( GenLists ); + GPA_GL( ListBase ); + GPA_GL( Begin ); + GPA_GL( Bitmap ); + GPA_GL( Color3b ); + GPA_GL( Color3bv ); + GPA_GL( Color3d ); + GPA_GL( Color3dv ); + GPA_GL( Color3f ); + GPA_GL( Color3fv ); + GPA_GL( Color3i ); + GPA_GL( Color3iv ); + GPA_GL( Color3s ); + GPA_GL( Color3sv ); + GPA_GL( Color3ub ); + GPA_GL( Color3ubv ); + GPA_GL( Color3ui ); + GPA_GL( Color3uiv ); + GPA_GL( Color3us ); + GPA_GL( Color3usv ); + GPA_GL( Color4b ); + GPA_GL( Color4bv ); + GPA_GL( Color4d ); + GPA_GL( Color4dv ); + GPA_GL( Color4f ); + GPA_GL( Color4fv ); + GPA_GL( Color4i ); + GPA_GL( Color4iv ); + GPA_GL( Color4s ); + GPA_GL( Color4sv ); + GPA_GL( Color4ub ); + GPA_GL( Color4ubv ); + GPA_GL( Color4ui ); + GPA_GL( Color4uiv ); + GPA_GL( Color4us ); + GPA_GL( Color4usv ); + GPA_GL( EdgeFlag ); + GPA_GL( EdgeFlagv ); + GPA_GL( End ); + GPA_GL( Indexd ); + GPA_GL( Indexdv ); + GPA_GL( Indexf ); + GPA_GL( Indexfv ); + GPA_GL( Indexi ); + GPA_GL( Indexiv ); + GPA_GL( Indexs ); + GPA_GL( Indexsv ); + GPA_GL( Normal3b ); + GPA_GL( Normal3bv ); + GPA_GL( Normal3d ); + GPA_GL( Normal3dv ); + GPA_GL( Normal3f ); + GPA_GL( Normal3fv ); + GPA_GL( Normal3i ); + GPA_GL( Normal3iv ); + GPA_GL( Normal3s ); + GPA_GL( Normal3sv ); + GPA_GL( RasterPos2d ); + GPA_GL( RasterPos2dv ); + GPA_GL( RasterPos2f ); + GPA_GL( RasterPos2fv ); + GPA_GL( RasterPos2i ); + GPA_GL( RasterPos2iv ); + GPA_GL( RasterPos2s ); + GPA_GL( RasterPos2sv ); + GPA_GL( RasterPos3d ); + GPA_GL( RasterPos3dv ); + GPA_GL( RasterPos3f ); + GPA_GL( RasterPos3fv ); + GPA_GL( RasterPos3i ); + GPA_GL( RasterPos3iv ); + GPA_GL( RasterPos3s ); + GPA_GL( RasterPos3sv ); + GPA_GL( RasterPos4d ); + GPA_GL( RasterPos4dv ); + GPA_GL( RasterPos4f ); + GPA_GL( RasterPos4fv ); + GPA_GL( RasterPos4i ); + GPA_GL( RasterPos4iv ); + GPA_GL( RasterPos4s ); + GPA_GL( RasterPos4sv ); + GPA_GL( Rectd ); + GPA_GL( Rectdv ); + GPA_GL( Rectf ); + GPA_GL( Rectfv ); + GPA_GL( Recti ); + GPA_GL( Rectiv ); + GPA_GL( Rects ); + GPA_GL( Rectsv ); + GPA_GL( TexCoord1d ); + GPA_GL( TexCoord1dv ); + GPA_GL( TexCoord1f ); + GPA_GL( TexCoord1fv ); + GPA_GL( TexCoord1i ); + GPA_GL( TexCoord1iv ); + GPA_GL( TexCoord1s ); + GPA_GL( TexCoord1sv ); + GPA_GL( TexCoord2d ); + GPA_GL( TexCoord2dv ); + GPA_GL( TexCoord2f ); + GPA_GL( TexCoord2fv ); + GPA_GL( TexCoord2i ); + GPA_GL( TexCoord2iv ); + GPA_GL( TexCoord2s ); + GPA_GL( TexCoord2sv ); + GPA_GL( TexCoord3d ); + GPA_GL( TexCoord3dv ); + GPA_GL( TexCoord3f ); + GPA_GL( TexCoord3fv ); + GPA_GL( TexCoord3i ); + GPA_GL( TexCoord3iv ); + GPA_GL( TexCoord3s ); + GPA_GL( TexCoord3sv ); + GPA_GL( TexCoord4d ); + GPA_GL( TexCoord4dv ); + GPA_GL( TexCoord4f ); + GPA_GL( TexCoord4fv ); + GPA_GL( TexCoord4i ); + GPA_GL( TexCoord4iv ); + GPA_GL( TexCoord4s ); + GPA_GL( TexCoord4sv ); + GPA_GL( Vertex2d ); + GPA_GL( Vertex2dv ); + GPA_GL( Vertex2f ); + GPA_GL( Vertex2fv ); + GPA_GL( Vertex2i ); + GPA_GL( Vertex2iv ); + GPA_GL( Vertex2s ); + GPA_GL( Vertex2sv ); + GPA_GL( Vertex3d ); + GPA_GL( Vertex3dv ); + GPA_GL( Vertex3f ); + GPA_GL( Vertex3fv ); + GPA_GL( Vertex3i ); + GPA_GL( Vertex3iv ); + GPA_GL( Vertex3s ); + GPA_GL( Vertex3sv ); + GPA_GL( Vertex4d ); + GPA_GL( Vertex4dv ); + GPA_GL( Vertex4f ); + GPA_GL( Vertex4fv ); + GPA_GL( Vertex4i ); + GPA_GL( Vertex4iv ); + GPA_GL( Vertex4s ); + GPA_GL( Vertex4sv ); + GPA_GL( ClipPlane ); + GPA_GL( ColorMaterial ); + GPA_GL( CullFace ); + GPA_GL( Fogf ); + GPA_GL( Fogfv ); + GPA_GL( Fogi ); + GPA_GL( Fogiv ); + GPA_GL( FrontFace ); + GPA_GL( Hint ); + GPA_GL( Lightf ); + GPA_GL( Lightfv ); + GPA_GL( Lighti ); + GPA_GL( Lightiv ); + GPA_GL( LightModelf ); + GPA_GL( LightModelfv ); + GPA_GL( LightModeli ); + GPA_GL( LightModeliv ); + GPA_GL( LineStipple ); + GPA_GL( LineWidth ); + GPA_GL( Materialf ); + GPA_GL( Materialfv ); + GPA_GL( Materiali ); + GPA_GL( Materialiv ); + GPA_GL( PointSize ); + GPA_GL( PolygonMode ); + GPA_GL( PolygonStipple ); + GPA_GL( Scissor ); + GPA_GL( ShadeModel ); + GPA_GL( TexParameterf ); + GPA_GL( TexParameterfv ); + GPA_GL( TexParameteri ); + GPA_GL( TexParameteriv ); + GPA_GL( TexImage1D ); + GPA_GL( TexImage2D ); + GPA_GL( TexEnvf ); + GPA_GL( TexEnvfv ); + GPA_GL( TexEnvi ); + GPA_GL( TexEnviv ); + GPA_GL( TexGend ); + GPA_GL( TexGendv ); + GPA_GL( TexGenf ); + GPA_GL( TexGenfv ); + GPA_GL( TexGeni ); + GPA_GL( TexGeniv ); + GPA_GL( FeedbackBuffer ); + GPA_GL( SelectBuffer ); + GPA_GL( RenderMode ); + GPA_GL( InitNames ); + GPA_GL( LoadName ); + GPA_GL( PassThrough ); + GPA_GL( PopName ); + GPA_GL( PushName ); + GPA_GL( DrawBuffer ); + GPA_GL( Clear ); + GPA_GL( ClearAccum ); + GPA_GL( ClearIndex ); + GPA_GL( ClearColor ); + GPA_GL( ClearStencil ); + GPA_GL( ClearDepth ); + GPA_GL( StencilMask ); + GPA_GL( ColorMask ); + GPA_GL( DepthMask ); + GPA_GL( IndexMask ); + GPA_GL( Accum ); + GPA_GL( Disable ); + GPA_GL( Enable ); + GPA_GL( Finish ); + GPA_GL( Flush ); + GPA_GL( PopAttrib ); + GPA_GL( PushAttrib ); + GPA_GL( Map1d ); + GPA_GL( Map1f ); + GPA_GL( Map2d ); + GPA_GL( Map2f ); + GPA_GL( MapGrid1d ); + GPA_GL( MapGrid1f ); + GPA_GL( MapGrid2d ); + GPA_GL( MapGrid2f ); + GPA_GL( EvalCoord1d ); + GPA_GL( EvalCoord1dv ); + GPA_GL( EvalCoord1f ); + GPA_GL( EvalCoord1fv ); + GPA_GL( EvalCoord2d ); + GPA_GL( EvalCoord2dv ); + GPA_GL( EvalCoord2f ); + GPA_GL( EvalCoord2fv ); + GPA_GL( EvalMesh1 ); + GPA_GL( EvalPoint1 ); + GPA_GL( EvalMesh2 ); + GPA_GL( EvalPoint2 ); + GPA_GL( AlphaFunc ); + GPA_GL( BlendFunc ); + GPA_GL( LogicOp ); + GPA_GL( StencilFunc ); + GPA_GL( StencilOp ); + GPA_GL( DepthFunc ); + GPA_GL( PixelZoom ); + GPA_GL( PixelTransferf ); + GPA_GL( PixelTransferi ); + GPA_GL( PixelStoref ); + GPA_GL( PixelStorei ); + GPA_GL( PixelMapfv ); + GPA_GL( PixelMapuiv ); + GPA_GL( PixelMapusv ); + GPA_GL( ReadBuffer ); + GPA_GL( CopyPixels ); + GPA_GL( ReadPixels ); + GPA_GL( DrawPixels ); + GPA_GL( GetBooleanv ); + GPA_GL( GetClipPlane ); + GPA_GL( GetDoublev ); + GPA_GL( GetError ); + GPA_GL( GetFloatv ); + GPA_GL( GetIntegerv ); + GPA_GL( GetLightfv ); + GPA_GL( GetLightiv ); + GPA_GL( GetMapdv ); + GPA_GL( GetMapfv ); + GPA_GL( GetMapiv ); + GPA_GL( GetMaterialfv ); + GPA_GL( GetMaterialiv ); + GPA_GL( GetPixelMapfv ); + GPA_GL( GetPixelMapuiv ); + GPA_GL( GetPixelMapusv ); + GPA_GL( GetPolygonStipple ); + GPA_GL( GetString ); + GPA_GL( GetTexEnvfv ); + GPA_GL( GetTexEnviv ); + GPA_GL( GetTexGendv ); + GPA_GL( GetTexGenfv ); + GPA_GL( GetTexGeniv ); + GPA_GL( GetTexImage ); + GPA_GL( GetTexParameterfv ); + GPA_GL( GetTexParameteriv ); + GPA_GL( GetTexLevelParameterfv ); + GPA_GL( GetTexLevelParameteriv ); + GPA_GL( IsEnabled ); + GPA_GL( IsList ); + GPA_GL( DepthRange ); + GPA_GL( Frustum ); + GPA_GL( LoadIdentity ); + GPA_GL( LoadMatrixf ); + GPA_GL( LoadMatrixd ); + GPA_GL( MatrixMode ); + GPA_GL( MultMatrixf ); + GPA_GL( MultMatrixd ); + GPA_GL( Ortho ); + GPA_GL( PopMatrix ); + GPA_GL( PushMatrix ); + GPA_GL( Rotated ); + GPA_GL( Rotatef ); + GPA_GL( Scaled ); + GPA_GL( Scalef ); + GPA_GL( Translated ); + GPA_GL( Translatef ); + GPA_GL( Viewport ); + GPA_GL( ArrayElement ); + GPA_GL( BindTexture ); + GPA_GL( ColorPointer ); + GPA_GL( DisableClientState ); + GPA_GL( DrawArrays ); + GPA_GL( DrawElements ); + GPA_GL( EdgeFlagPointer ); + GPA_GL( EnableClientState ); + GPA_GL( IndexPointer ); + GPA_GL( Indexub ); + GPA_GL( Indexubv ); + GPA_GL( InterleavedArrays ); + GPA_GL( NormalPointer ); + GPA_GL( PolygonOffset ); + GPA_GL( TexCoordPointer ); + GPA_GL( VertexPointer ); + GPA_GL( AreTexturesResident ); + GPA_GL( CopyTexImage1D ); + GPA_GL( CopyTexImage2D ); + GPA_GL( CopyTexSubImage1D ); + GPA_GL( CopyTexSubImage2D ); + GPA_GL( DeleteTextures ); + GPA_GL( GenTextures ); + GPA_GL( GetPointerv ); + GPA_GL( IsTexture ); + GPA_GL( PrioritizeTextures ); + GPA_GL( TexSubImage1D ); + GPA_GL( TexSubImage2D ); + GPA_GL( PopClientAttrib ); + GPA_GL( PushClientAttrib ); +} + +PGLCLTPROCTABLE APIENTRY +DrvSetContext( + HDC hdc, + DHGLRC dhglrc, + PFN_SETPROCTABLE pfnSetProcTable ) +{ + PGLCLTPROCTABLE result = NULL; + + if (!stw_icd) + return result; + + pipe_mutex_lock( stw_icd->mutex ); + { + struct stw_context *ctx; + + debug_printf( "%s( 0x%p, %u, 0x%p )\n", + __FUNCTION__, hdc, dhglrc, pfnSetProcTable ); + + /* Although WGL allows different dispatch entrypoints per + */ + if (!stw_icd->cpt_initialized) { + init_proc_table( &stw_icd->cpt ); + stw_icd->cpt_initialized = TRUE; + } + + ctx = lookup_context( stw_icd, dhglrc ); + if (ctx == NULL) + goto done; + + if (!stw_make_current( hdc, ctx )) + goto done; + + result = &stw_icd->cpt; + } +done: + pipe_mutex_unlock( stw_icd->mutex ); + + return result; +} + +int APIENTRY +DrvSetLayerPaletteEntries( + HDC hdc, + INT iLayerPlane, + INT iStart, + INT cEntries, + CONST COLORREF *pcr ) +{ + debug_printf( "%s\n", __FUNCTION__ ); + + return 0; +} + +BOOL APIENTRY +DrvSetPixelFormat( + HDC hdc, + LONG iPixelFormat ) +{ + BOOL r; + + r = stw_pixelformat_set( hdc, iPixelFormat ); + + debug_printf( "%s( %p, %d ) = %s\n", __FUNCTION__, hdc, iPixelFormat, r ? "TRUE" : "FALSE" ); + + return r; +} + +BOOL APIENTRY +DrvShareLists( + DHGLRC dhglrc1, + DHGLRC dhglrc2 ) +{ + debug_printf( "%s\n", __FUNCTION__ ); + + return FALSE; +} + +BOOL APIENTRY +DrvSwapBuffers( + HDC hdc ) +{ + debug_printf( "%s( %p )\n", __FUNCTION__, hdc ); + + return stw_swap_buffers( hdc ); +} + +BOOL APIENTRY +DrvSwapLayerBuffers( + HDC hdc, + UINT fuPlanes ) +{ + debug_printf( "%s\n", __FUNCTION__ ); + + return FALSE; +} + +BOOL APIENTRY +DrvValidateVersion( + ULONG ulVersion ) +{ + debug_printf( "%s( %u )\n", __FUNCTION__, ulVersion ); + + /* TODO: get the expected version from the winsys */ + + return ulVersion == 1; +} diff --git a/src/gallium/state_trackers/wgl/icd/stw_icd.h b/src/gallium/state_trackers/wgl/icd/stw_icd.h new file mode 100644 index 00000000000..8e676fb5b74 --- /dev/null +++ b/src/gallium/state_trackers/wgl/icd/stw_icd.h @@ -0,0 +1,489 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef DRV_H +#define DRV_H + + +#include <windows.h> + +#include "GL/gl.h" + + +typedef ULONG DHGLRC; + +#define OPENGL_VERSION_110_ENTRIES 336 + +struct __GLdispatchTableRec +{ + void (GLAPIENTRY * NewList)(GLuint, GLenum); + void (GLAPIENTRY * EndList)(void); + void (GLAPIENTRY * CallList)(GLuint); + void (GLAPIENTRY * CallLists)(GLsizei, GLenum, const GLvoid *); + void (GLAPIENTRY * DeleteLists)(GLuint, GLsizei); + GLuint (GLAPIENTRY * GenLists)(GLsizei); + void (GLAPIENTRY * ListBase)(GLuint); + void (GLAPIENTRY * Begin)(GLenum); + void (GLAPIENTRY * Bitmap)(GLsizei, GLsizei, GLfloat, GLfloat, GLfloat, GLfloat, const GLubyte *); + void (GLAPIENTRY * Color3b)(GLbyte, GLbyte, GLbyte); + void (GLAPIENTRY * Color3bv)(const GLbyte *); + void (GLAPIENTRY * Color3d)(GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * Color3dv)(const GLdouble *); + void (GLAPIENTRY * Color3f)(GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * Color3fv)(const GLfloat *); + void (GLAPIENTRY * Color3i)(GLint, GLint, GLint); + void (GLAPIENTRY * Color3iv)(const GLint *); + void (GLAPIENTRY * Color3s)(GLshort, GLshort, GLshort); + void (GLAPIENTRY * Color3sv)(const GLshort *); + void (GLAPIENTRY * Color3ub)(GLubyte, GLubyte, GLubyte); + void (GLAPIENTRY * Color3ubv)(const GLubyte *); + void (GLAPIENTRY * Color3ui)(GLuint, GLuint, GLuint); + void (GLAPIENTRY * Color3uiv)(const GLuint *); + void (GLAPIENTRY * Color3us)(GLushort, GLushort, GLushort); + void (GLAPIENTRY * Color3usv)(const GLushort *); + void (GLAPIENTRY * Color4b)(GLbyte, GLbyte, GLbyte, GLbyte); + void (GLAPIENTRY * Color4bv)(const GLbyte *); + void (GLAPIENTRY * Color4d)(GLdouble, GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * Color4dv)(const GLdouble *); + void (GLAPIENTRY * Color4f)(GLfloat, GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * Color4fv)(const GLfloat *); + void (GLAPIENTRY * Color4i)(GLint, GLint, GLint, GLint); + void (GLAPIENTRY * Color4iv)(const GLint *); + void (GLAPIENTRY * Color4s)(GLshort, GLshort, GLshort, GLshort); + void (GLAPIENTRY * Color4sv)(const GLshort *); + void (GLAPIENTRY * Color4ub)(GLubyte, GLubyte, GLubyte, GLubyte); + void (GLAPIENTRY * Color4ubv)(const GLubyte *); + void (GLAPIENTRY * Color4ui)(GLuint, GLuint, GLuint, GLuint); + void (GLAPIENTRY * Color4uiv)(const GLuint *); + void (GLAPIENTRY * Color4us)(GLushort, GLushort, GLushort, GLushort); + void (GLAPIENTRY * Color4usv)(const GLushort *); + void (GLAPIENTRY * EdgeFlag)(GLboolean); + void (GLAPIENTRY * EdgeFlagv)(const GLboolean *); + void (GLAPIENTRY * End)(void); + void (GLAPIENTRY * Indexd)(GLdouble); + void (GLAPIENTRY * Indexdv)(const GLdouble *); + void (GLAPIENTRY * Indexf)(GLfloat); + void (GLAPIENTRY * Indexfv)(const GLfloat *); + void (GLAPIENTRY * Indexi)(GLint); + void (GLAPIENTRY * Indexiv)(const GLint *); + void (GLAPIENTRY * Indexs)(GLshort); + void (GLAPIENTRY * Indexsv)(const GLshort *); + void (GLAPIENTRY * Normal3b)(GLbyte, GLbyte, GLbyte); + void (GLAPIENTRY * Normal3bv)(const GLbyte *); + void (GLAPIENTRY * Normal3d)(GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * Normal3dv)(const GLdouble *); + void (GLAPIENTRY * Normal3f)(GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * Normal3fv)(const GLfloat *); + void (GLAPIENTRY * Normal3i)(GLint, GLint, GLint); + void (GLAPIENTRY * Normal3iv)(const GLint *); + void (GLAPIENTRY * Normal3s)(GLshort, GLshort, GLshort); + void (GLAPIENTRY * Normal3sv)(const GLshort *); + void (GLAPIENTRY * RasterPos2d)(GLdouble, GLdouble); + void (GLAPIENTRY * RasterPos2dv)(const GLdouble *); + void (GLAPIENTRY * RasterPos2f)(GLfloat, GLfloat); + void (GLAPIENTRY * RasterPos2fv)(const GLfloat *); + void (GLAPIENTRY * RasterPos2i)(GLint, GLint); + void (GLAPIENTRY * RasterPos2iv)(const GLint *); + void (GLAPIENTRY * RasterPos2s)(GLshort, GLshort); + void (GLAPIENTRY * RasterPos2sv)(const GLshort *); + void (GLAPIENTRY * RasterPos3d)(GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * RasterPos3dv)(const GLdouble *); + void (GLAPIENTRY * RasterPos3f)(GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * RasterPos3fv)(const GLfloat *); + void (GLAPIENTRY * RasterPos3i)(GLint, GLint, GLint); + void (GLAPIENTRY * RasterPos3iv)(const GLint *); + void (GLAPIENTRY * RasterPos3s)(GLshort, GLshort, GLshort); + void (GLAPIENTRY * RasterPos3sv)(const GLshort *); + void (GLAPIENTRY * RasterPos4d)(GLdouble, GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * RasterPos4dv)(const GLdouble *); + void (GLAPIENTRY * RasterPos4f)(GLfloat, GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * RasterPos4fv)(const GLfloat *); + void (GLAPIENTRY * RasterPos4i)(GLint, GLint, GLint, GLint); + void (GLAPIENTRY * RasterPos4iv)(const GLint *); + void (GLAPIENTRY * RasterPos4s)(GLshort, GLshort, GLshort, GLshort); + void (GLAPIENTRY * RasterPos4sv)(const GLshort *); + void (GLAPIENTRY * Rectd)(GLdouble, GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * Rectdv)(const GLdouble *, const GLdouble *); + void (GLAPIENTRY * Rectf)(GLfloat, GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * Rectfv)(const GLfloat *, const GLfloat *); + void (GLAPIENTRY * Recti)(GLint, GLint, GLint, GLint); + void (GLAPIENTRY * Rectiv)(const GLint *, const GLint *); + void (GLAPIENTRY * Rects)(GLshort, GLshort, GLshort, GLshort); + void (GLAPIENTRY * Rectsv)(const GLshort *, const GLshort *); + void (GLAPIENTRY * TexCoord1d)(GLdouble); + void (GLAPIENTRY * TexCoord1dv)(const GLdouble *); + void (GLAPIENTRY * TexCoord1f)(GLfloat); + void (GLAPIENTRY * TexCoord1fv)(const GLfloat *); + void (GLAPIENTRY * TexCoord1i)(GLint); + void (GLAPIENTRY * TexCoord1iv)(const GLint *); + void (GLAPIENTRY * TexCoord1s)(GLshort); + void (GLAPIENTRY * TexCoord1sv)(const GLshort *); + void (GLAPIENTRY * TexCoord2d)(GLdouble, GLdouble); + void (GLAPIENTRY * TexCoord2dv)(const GLdouble *); + void (GLAPIENTRY * TexCoord2f)(GLfloat, GLfloat); + void (GLAPIENTRY * TexCoord2fv)(const GLfloat *); + void (GLAPIENTRY * TexCoord2i)(GLint, GLint); + void (GLAPIENTRY * TexCoord2iv)(const GLint *); + void (GLAPIENTRY * TexCoord2s)(GLshort, GLshort); + void (GLAPIENTRY * TexCoord2sv)(const GLshort *); + void (GLAPIENTRY * TexCoord3d)(GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * TexCoord3dv)(const GLdouble *); + void (GLAPIENTRY * TexCoord3f)(GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * TexCoord3fv)(const GLfloat *); + void (GLAPIENTRY * TexCoord3i)(GLint, GLint, GLint); + void (GLAPIENTRY * TexCoord3iv)(const GLint *); + void (GLAPIENTRY * TexCoord3s)(GLshort, GLshort, GLshort); + void (GLAPIENTRY * TexCoord3sv)(const GLshort *); + void (GLAPIENTRY * TexCoord4d)(GLdouble, GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * TexCoord4dv)(const GLdouble *); + void (GLAPIENTRY * TexCoord4f)(GLfloat, GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * TexCoord4fv)(const GLfloat *); + void (GLAPIENTRY * TexCoord4i)(GLint, GLint, GLint, GLint); + void (GLAPIENTRY * TexCoord4iv)(const GLint *); + void (GLAPIENTRY * TexCoord4s)(GLshort, GLshort, GLshort, GLshort); + void (GLAPIENTRY * TexCoord4sv)(const GLshort *); + void (GLAPIENTRY * Vertex2d)(GLdouble, GLdouble); + void (GLAPIENTRY * Vertex2dv)(const GLdouble *); + void (GLAPIENTRY * Vertex2f)(GLfloat, GLfloat); + void (GLAPIENTRY * Vertex2fv)(const GLfloat *); + void (GLAPIENTRY * Vertex2i)(GLint, GLint); + void (GLAPIENTRY * Vertex2iv)(const GLint *); + void (GLAPIENTRY * Vertex2s)(GLshort, GLshort); + void (GLAPIENTRY * Vertex2sv)(const GLshort *); + void (GLAPIENTRY * Vertex3d)(GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * Vertex3dv)(const GLdouble *); + void (GLAPIENTRY * Vertex3f)(GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * Vertex3fv)(const GLfloat *); + void (GLAPIENTRY * Vertex3i)(GLint, GLint, GLint); + void (GLAPIENTRY * Vertex3iv)(const GLint *); + void (GLAPIENTRY * Vertex3s)(GLshort, GLshort, GLshort); + void (GLAPIENTRY * Vertex3sv)(const GLshort *); + void (GLAPIENTRY * Vertex4d)(GLdouble, GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * Vertex4dv)(const GLdouble *); + void (GLAPIENTRY * Vertex4f)(GLfloat, GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * Vertex4fv)(const GLfloat *); + void (GLAPIENTRY * Vertex4i)(GLint, GLint, GLint, GLint); + void (GLAPIENTRY * Vertex4iv)(const GLint *); + void (GLAPIENTRY * Vertex4s)(GLshort, GLshort, GLshort, GLshort); + void (GLAPIENTRY * Vertex4sv)(const GLshort *); + void (GLAPIENTRY * ClipPlane)(GLenum, const GLdouble *); + void (GLAPIENTRY * ColorMaterial)(GLenum, GLenum); + void (GLAPIENTRY * CullFace)(GLenum); + void (GLAPIENTRY * Fogf)(GLenum, GLfloat); + void (GLAPIENTRY * Fogfv)(GLenum, const GLfloat *); + void (GLAPIENTRY * Fogi)(GLenum, GLint); + void (GLAPIENTRY * Fogiv)(GLenum, const GLint *); + void (GLAPIENTRY * FrontFace)(GLenum); + void (GLAPIENTRY * Hint)(GLenum, GLenum); + void (GLAPIENTRY * Lightf)(GLenum, GLenum, GLfloat); + void (GLAPIENTRY * Lightfv)(GLenum, GLenum, const GLfloat *); + void (GLAPIENTRY * Lighti)(GLenum, GLenum, GLint); + void (GLAPIENTRY * Lightiv)(GLenum, GLenum, const GLint *); + void (GLAPIENTRY * LightModelf)(GLenum, GLfloat); + void (GLAPIENTRY * LightModelfv)(GLenum, const GLfloat *); + void (GLAPIENTRY * LightModeli)(GLenum, GLint); + void (GLAPIENTRY * LightModeliv)(GLenum, const GLint *); + void (GLAPIENTRY * LineStipple)(GLint, GLushort); + void (GLAPIENTRY * LineWidth)(GLfloat); + void (GLAPIENTRY * Materialf)(GLenum, GLenum, GLfloat); + void (GLAPIENTRY * Materialfv)(GLenum, GLenum, const GLfloat *); + void (GLAPIENTRY * Materiali)(GLenum, GLenum, GLint); + void (GLAPIENTRY * Materialiv)(GLenum, GLenum, const GLint *); + void (GLAPIENTRY * PointSize)(GLfloat); + void (GLAPIENTRY * PolygonMode)(GLenum, GLenum); + void (GLAPIENTRY * PolygonStipple)(const GLubyte *); + void (GLAPIENTRY * Scissor)(GLint, GLint, GLsizei, GLsizei); + void (GLAPIENTRY * ShadeModel)(GLenum); + void (GLAPIENTRY * TexParameterf)(GLenum, GLenum, GLfloat); + void (GLAPIENTRY * TexParameterfv)(GLenum, GLenum, const GLfloat *); + void (GLAPIENTRY * TexParameteri)(GLenum, GLenum, GLint); + void (GLAPIENTRY * TexParameteriv)(GLenum, GLenum, const GLint *); + void (GLAPIENTRY * TexImage1D)(GLenum, GLint, GLint, GLsizei, GLint, GLenum, GLenum, const GLvoid *); + void (GLAPIENTRY * TexImage2D)(GLenum, GLint, GLint, GLsizei, GLsizei, GLint, GLenum, GLenum, const GLvoid *); + void (GLAPIENTRY * TexEnvf)(GLenum, GLenum, GLfloat); + void (GLAPIENTRY * TexEnvfv)(GLenum, GLenum, const GLfloat *); + void (GLAPIENTRY * TexEnvi)(GLenum, GLenum, GLint); + void (GLAPIENTRY * TexEnviv)(GLenum, GLenum, const GLint *); + void (GLAPIENTRY * TexGend)(GLenum, GLenum, GLdouble); + void (GLAPIENTRY * TexGendv)(GLenum, GLenum, const GLdouble *); + void (GLAPIENTRY * TexGenf)(GLenum, GLenum, GLfloat); + void (GLAPIENTRY * TexGenfv)(GLenum, GLenum, const GLfloat *); + void (GLAPIENTRY * TexGeni)(GLenum, GLenum, GLint); + void (GLAPIENTRY * TexGeniv)(GLenum, GLenum, const GLint *); + void (GLAPIENTRY * FeedbackBuffer)(GLsizei, GLenum, GLfloat *); + void (GLAPIENTRY * SelectBuffer)(GLsizei, GLuint *); + GLint (GLAPIENTRY * RenderMode)(GLenum); + void (GLAPIENTRY * InitNames)(void); + void (GLAPIENTRY * LoadName)(GLuint); + void (GLAPIENTRY * PassThrough)(GLfloat); + void (GLAPIENTRY * PopName)(void); + void (GLAPIENTRY * PushName)(GLuint); + void (GLAPIENTRY * DrawBuffer)(GLenum); + void (GLAPIENTRY * Clear)(GLbitfield); + void (GLAPIENTRY * ClearAccum)(GLfloat, GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * ClearIndex)(GLfloat); + void (GLAPIENTRY * ClearColor)(GLclampf, GLclampf, GLclampf, GLclampf); + void (GLAPIENTRY * ClearStencil)(GLint); + void (GLAPIENTRY * ClearDepth)(GLclampd); + void (GLAPIENTRY * StencilMask)(GLuint); + void (GLAPIENTRY * ColorMask)(GLboolean, GLboolean, GLboolean, GLboolean); + void (GLAPIENTRY * DepthMask)(GLboolean); + void (GLAPIENTRY * IndexMask)(GLuint); + void (GLAPIENTRY * Accum)(GLenum, GLfloat); + void (GLAPIENTRY * Disable)(GLenum); + void (GLAPIENTRY * Enable)(GLenum); + void (GLAPIENTRY * Finish)(void); + void (GLAPIENTRY * Flush)(void); + void (GLAPIENTRY * PopAttrib)(void); + void (GLAPIENTRY * PushAttrib)(GLbitfield); + void (GLAPIENTRY * Map1d)(GLenum, GLdouble, GLdouble, GLint, GLint, const GLdouble *); + void (GLAPIENTRY * Map1f)(GLenum, GLfloat, GLfloat, GLint, GLint, const GLfloat *); + void (GLAPIENTRY * Map2d)(GLenum, GLdouble, GLdouble, GLint, GLint, GLdouble, GLdouble, GLint, GLint, const GLdouble *); + void (GLAPIENTRY * Map2f)(GLenum, GLfloat, GLfloat, GLint, GLint, GLfloat, GLfloat, GLint, GLint, const GLfloat *); + void (GLAPIENTRY * MapGrid1d)(GLint, GLdouble, GLdouble); + void (GLAPIENTRY * MapGrid1f)(GLint, GLfloat, GLfloat); + void (GLAPIENTRY * MapGrid2d)(GLint, GLdouble, GLdouble, GLint, GLdouble, GLdouble); + void (GLAPIENTRY * MapGrid2f)(GLint, GLfloat, GLfloat, GLint, GLfloat, GLfloat); + void (GLAPIENTRY * EvalCoord1d)(GLdouble); + void (GLAPIENTRY * EvalCoord1dv)(const GLdouble *); + void (GLAPIENTRY * EvalCoord1f)(GLfloat); + void (GLAPIENTRY * EvalCoord1fv)(const GLfloat *); + void (GLAPIENTRY * EvalCoord2d)(GLdouble, GLdouble); + void (GLAPIENTRY * EvalCoord2dv)(const GLdouble *); + void (GLAPIENTRY * EvalCoord2f)(GLfloat, GLfloat); + void (GLAPIENTRY * EvalCoord2fv)(const GLfloat *); + void (GLAPIENTRY * EvalMesh1)(GLenum, GLint, GLint); + void (GLAPIENTRY * EvalPoint1)(GLint); + void (GLAPIENTRY * EvalMesh2)(GLenum, GLint, GLint, GLint, GLint); + void (GLAPIENTRY * EvalPoint2)(GLint, GLint); + void (GLAPIENTRY * AlphaFunc)(GLenum, GLclampf); + void (GLAPIENTRY * BlendFunc)(GLenum, GLenum); + void (GLAPIENTRY * LogicOp)(GLenum); + void (GLAPIENTRY * StencilFunc)(GLenum, GLint, GLuint); + void (GLAPIENTRY * StencilOp)(GLenum, GLenum, GLenum); + void (GLAPIENTRY * DepthFunc)(GLenum); + void (GLAPIENTRY * PixelZoom)(GLfloat, GLfloat); + void (GLAPIENTRY * PixelTransferf)(GLenum, GLfloat); + void (GLAPIENTRY * PixelTransferi)(GLenum, GLint); + void (GLAPIENTRY * PixelStoref)(GLenum, GLfloat); + void (GLAPIENTRY * PixelStorei)(GLenum, GLint); + void (GLAPIENTRY * PixelMapfv)(GLenum, GLint, const GLfloat *); + void (GLAPIENTRY * PixelMapuiv)(GLenum, GLint, const GLuint *); + void (GLAPIENTRY * PixelMapusv)(GLenum, GLint, const GLushort *); + void (GLAPIENTRY * ReadBuffer)(GLenum); + void (GLAPIENTRY * CopyPixels)(GLint, GLint, GLsizei, GLsizei, GLenum); + void (GLAPIENTRY * ReadPixels)(GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, GLvoid *); + void (GLAPIENTRY * DrawPixels)(GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); + void (GLAPIENTRY * GetBooleanv)(GLenum, GLboolean *); + void (GLAPIENTRY * GetClipPlane)(GLenum, GLdouble *); + void (GLAPIENTRY * GetDoublev)(GLenum, GLdouble *); + GLenum (GLAPIENTRY * GetError)(void); + void (GLAPIENTRY * GetFloatv)(GLenum, GLfloat *); + void (GLAPIENTRY * GetIntegerv)(GLenum, GLint *); + void (GLAPIENTRY * GetLightfv)(GLenum, GLenum, GLfloat *); + void (GLAPIENTRY * GetLightiv)(GLenum, GLenum, GLint *); + void (GLAPIENTRY * GetMapdv)(GLenum, GLenum, GLdouble *); + void (GLAPIENTRY * GetMapfv)(GLenum, GLenum, GLfloat *); + void (GLAPIENTRY * GetMapiv)(GLenum, GLenum, GLint *); + void (GLAPIENTRY * GetMaterialfv)(GLenum, GLenum, GLfloat *); + void (GLAPIENTRY * GetMaterialiv)(GLenum, GLenum, GLint *); + void (GLAPIENTRY * GetPixelMapfv)(GLenum, GLfloat *); + void (GLAPIENTRY * GetPixelMapuiv)(GLenum, GLuint *); + void (GLAPIENTRY * GetPixelMapusv)(GLenum, GLushort *); + void (GLAPIENTRY * GetPolygonStipple)(GLubyte *); + const GLubyte * (GLAPIENTRY * GetString)(GLenum); + void (GLAPIENTRY * GetTexEnvfv)(GLenum, GLenum, GLfloat *); + void (GLAPIENTRY * GetTexEnviv)(GLenum, GLenum, GLint *); + void (GLAPIENTRY * GetTexGendv)(GLenum, GLenum, GLdouble *); + void (GLAPIENTRY * GetTexGenfv)(GLenum, GLenum, GLfloat *); + void (GLAPIENTRY * GetTexGeniv)(GLenum, GLenum, GLint *); + void (GLAPIENTRY * GetTexImage)(GLenum, GLint, GLenum, GLenum, GLvoid *); + void (GLAPIENTRY * GetTexParameterfv)(GLenum, GLenum, GLfloat *); + void (GLAPIENTRY * GetTexParameteriv)(GLenum, GLenum, GLint *); + void (GLAPIENTRY * GetTexLevelParameterfv)(GLenum, GLint, GLenum, GLfloat *); + void (GLAPIENTRY * GetTexLevelParameteriv)(GLenum, GLint, GLenum, GLint *); + GLboolean (GLAPIENTRY * IsEnabled)(GLenum); + GLboolean (GLAPIENTRY * IsList)(GLuint); + void (GLAPIENTRY * DepthRange)(GLclampd, GLclampd); + void (GLAPIENTRY * Frustum)(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * LoadIdentity)(void); + void (GLAPIENTRY * LoadMatrixf)(const GLfloat *); + void (GLAPIENTRY * LoadMatrixd)(const GLdouble *); + void (GLAPIENTRY * MatrixMode)(GLenum); + void (GLAPIENTRY * MultMatrixf)(const GLfloat *); + void (GLAPIENTRY * MultMatrixd)(const GLdouble *); + void (GLAPIENTRY * Ortho)(GLdouble, GLdouble, GLdouble, GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * PopMatrix)(void); + void (GLAPIENTRY * PushMatrix)(void); + void (GLAPIENTRY * Rotated)(GLdouble, GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * Rotatef)(GLfloat, GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * Scaled)(GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * Scalef)(GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * Translated)(GLdouble, GLdouble, GLdouble); + void (GLAPIENTRY * Translatef)(GLfloat, GLfloat, GLfloat); + void (GLAPIENTRY * Viewport)(GLint, GLint, GLsizei, GLsizei); + void (GLAPIENTRY * ArrayElement)(GLint); + void (GLAPIENTRY * BindTexture)(GLenum, GLuint); + void (GLAPIENTRY * ColorPointer)(GLint, GLenum, GLsizei, const GLvoid *); + void (GLAPIENTRY * DisableClientState)(GLenum); + void (GLAPIENTRY * DrawArrays)(GLenum, GLint, GLsizei); + void (GLAPIENTRY * DrawElements)(GLenum, GLsizei, GLenum, const GLvoid *); + void (GLAPIENTRY * EdgeFlagPointer)(GLsizei, const GLvoid *); + void (GLAPIENTRY * EnableClientState)(GLenum); + void (GLAPIENTRY * IndexPointer)(GLenum, GLsizei, const GLvoid *); + void (GLAPIENTRY * Indexub)(GLubyte); + void (GLAPIENTRY * Indexubv)(const GLubyte *); + void (GLAPIENTRY * InterleavedArrays)(GLenum, GLsizei, const GLvoid *); + void (GLAPIENTRY * NormalPointer)(GLenum, GLsizei, const GLvoid *); + void (GLAPIENTRY * PolygonOffset)(GLfloat, GLfloat); + void (GLAPIENTRY * TexCoordPointer)(GLint, GLenum, GLsizei, const GLvoid *); + void (GLAPIENTRY * VertexPointer)(GLint, GLenum, GLsizei, const GLvoid *); + GLboolean (GLAPIENTRY * AreTexturesResident)(GLsizei, const GLuint *, GLboolean *); + void (GLAPIENTRY * CopyTexImage1D)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLint); + void (GLAPIENTRY * CopyTexImage2D)(GLenum, GLint, GLenum, GLint, GLint, GLsizei, GLsizei, GLint); + void (GLAPIENTRY * CopyTexSubImage1D)(GLenum, GLint, GLint, GLint, GLint, GLsizei); + void (GLAPIENTRY * CopyTexSubImage2D)(GLenum, GLint, GLint, GLint, GLint, GLint, GLsizei, GLsizei); + void (GLAPIENTRY * DeleteTextures)(GLsizei, const GLuint *); + void (GLAPIENTRY * GenTextures)(GLsizei, GLuint *); + void (GLAPIENTRY * GetPointerv)(GLenum, GLvoid **); + GLboolean (GLAPIENTRY * IsTexture)(GLuint); + void (GLAPIENTRY * PrioritizeTextures)(GLsizei, const GLuint *, const GLclampf *); + void (GLAPIENTRY * TexSubImage1D)(GLenum, GLint, GLint, GLsizei, GLenum, GLenum, const GLvoid *); + void (GLAPIENTRY * TexSubImage2D)(GLenum, GLint, GLint, GLint, GLsizei, GLsizei, GLenum, GLenum, const GLvoid *); + void (GLAPIENTRY * PopClientAttrib)(void); + void (GLAPIENTRY * PushClientAttrib)(GLbitfield); +}; + +typedef struct __GLdispatchTableRec GLDISPATCHTABLE; + +typedef struct _GLCLTPROCTABLE +{ + int cEntries; + GLDISPATCHTABLE glDispatchTable; +} GLCLTPROCTABLE, * PGLCLTPROCTABLE; + +typedef VOID (APIENTRY * PFN_SETPROCTABLE)(PGLCLTPROCTABLE); + +BOOL APIENTRY +DrvCopyContext( + DHGLRC dhrcSource, + DHGLRC dhrcDest, + UINT fuMask ); + +DHGLRC APIENTRY +DrvCreateLayerContext( + HDC hdc, + INT iLayerPlane ); + +DHGLRC APIENTRY +DrvCreateContext( + HDC hdc ); + +BOOL APIENTRY +DrvDeleteContext( + DHGLRC dhglrc ); + +BOOL APIENTRY +DrvDescribeLayerPlane( + HDC hdc, + INT iPixelFormat, + INT iLayerPlane, + UINT nBytes, + LPLAYERPLANEDESCRIPTOR plpd ); + +LONG APIENTRY +DrvDescribePixelFormat( + HDC hdc, + INT iPixelFormat, + ULONG cjpfd, + PIXELFORMATDESCRIPTOR *ppfd ); + +int APIENTRY +DrvGetLayerPaletteEntries( + HDC hdc, + INT iLayerPlane, + INT iStart, + INT cEntries, + COLORREF *pcr ); + +PROC APIENTRY +DrvGetProcAddress( + LPCSTR lpszProc ); + +BOOL APIENTRY +DrvRealizeLayerPalette( + HDC hdc, + INT iLayerPlane, + BOOL bRealize ); + +BOOL APIENTRY +DrvReleaseContext( + DHGLRC dhglrc ); + +void APIENTRY +DrvSetCallbackProcs( + INT nProcs, + PROC *pProcs ); + +PGLCLTPROCTABLE APIENTRY +DrvSetContext( + HDC hdc, + DHGLRC dhglrc, + PFN_SETPROCTABLE pfnSetProcTable ); + +int APIENTRY +DrvSetLayerPaletteEntries( + HDC hdc, + INT iLayerPlane, + INT iStart, + INT cEntries, + CONST COLORREF *pcr ); + +BOOL APIENTRY +DrvSetPixelFormat( + HDC hdc, + LONG iPixelFormat ); + +BOOL APIENTRY +DrvShareLists( + DHGLRC dhglrc1, + DHGLRC dhglrc2 ); + +BOOL APIENTRY +DrvSwapBuffers( + HDC hdc ); + +BOOL APIENTRY +DrvSwapLayerBuffers( + HDC hdc, + UINT fuPlanes ); + +BOOL APIENTRY +DrvValidateVersion( + ULONG ulVersion ); + +#endif /* DRV_H */ diff --git a/src/gallium/state_trackers/wgl/opengl32.def b/src/gallium/state_trackers/wgl/opengl32.def new file mode 100644 index 00000000000..596417ed844 --- /dev/null +++ b/src/gallium/state_trackers/wgl/opengl32.def @@ -0,0 +1,388 @@ +EXPORTS +; GlmfBeginGlsBlock +; GlmfCloseMetaFile +; GlmfEndGlsBlock +; GlmfEndPlayback +; GlmfInitPlayback +; GlmfPlayGlsRecord + glAccum + glAlphaFunc + glAreTexturesResident + glArrayElement + glBegin + glBindTexture + glBitmap + glBlendFunc + glCallList + glCallLists + glClear + glClearAccum + glClearColor + glClearDepth + glClearIndex + glClearStencil + glClipPlane + glColor3b + glColor3bv + glColor3d + glColor3dv + glColor3f + glColor3fv + glColor3i + glColor3iv + glColor3s + glColor3sv + glColor3ub + glColor3ubv + glColor3ui + glColor3uiv + glColor3us + glColor3usv + glColor4b + glColor4bv + glColor4d + glColor4dv + glColor4f + glColor4fv + glColor4i + glColor4iv + glColor4s + glColor4sv + glColor4ub + glColor4ubv + glColor4ui + glColor4uiv + glColor4us + glColor4usv + glColorMask + glColorMaterial + glColorPointer + glCopyPixels + glCopyTexImage1D + glCopyTexImage2D + glCopyTexSubImage1D + glCopyTexSubImage2D + glCullFace +; glDebugEntry + glDeleteLists + glDeleteTextures + glDepthFunc + glDepthMask + glDepthRange + glDisable + glDisableClientState + glDrawArrays + glDrawBuffer + glDrawElements + glDrawPixels + glEdgeFlag + glEdgeFlagPointer + glEdgeFlagv + glEnable + glEnableClientState + glEnd + glEndList + glEvalCoord1d + glEvalCoord1dv + glEvalCoord1f + glEvalCoord1fv + glEvalCoord2d + glEvalCoord2dv + glEvalCoord2f + glEvalCoord2fv + glEvalMesh1 + glEvalMesh2 + glEvalPoint1 + glEvalPoint2 + glFeedbackBuffer + glFinish + glFlush + glFogf + glFogfv + glFogi + glFogiv + glFrontFace + glFrustum + glGenLists + glGenTextures + glGetBooleanv + glGetClipPlane + glGetDoublev + glGetError + glGetFloatv + glGetIntegerv + glGetLightfv + glGetLightiv + glGetMapdv + glGetMapfv + glGetMapiv + glGetMaterialfv + glGetMaterialiv + glGetPixelMapfv + glGetPixelMapuiv + glGetPixelMapusv + glGetPointerv + glGetPolygonStipple + glGetString + glGetTexEnvfv + glGetTexEnviv + glGetTexGendv + glGetTexGenfv + glGetTexGeniv + glGetTexImage + glGetTexLevelParameterfv + glGetTexLevelParameteriv + glGetTexParameterfv + glGetTexParameteriv + glHint + glIndexMask + glIndexPointer + glIndexd + glIndexdv + glIndexf + glIndexfv + glIndexi + glIndexiv + glIndexs + glIndexsv + glIndexub + glIndexubv + glInitNames + glInterleavedArrays + glIsEnabled + glIsList + glIsTexture + glLightModelf + glLightModelfv + glLightModeli + glLightModeliv + glLightf + glLightfv + glLighti + glLightiv + glLineStipple + glLineWidth + glListBase + glLoadIdentity + glLoadMatrixd + glLoadMatrixf + glLoadName + glLogicOp + glMap1d + glMap1f + glMap2d + glMap2f + glMapGrid1d + glMapGrid1f + glMapGrid2d + glMapGrid2f + glMaterialf + glMaterialfv + glMateriali + glMaterialiv + glMatrixMode + glMultMatrixd + glMultMatrixf + glNewList + glNormal3b + glNormal3bv + glNormal3d + glNormal3dv + glNormal3f + glNormal3fv + glNormal3i + glNormal3iv + glNormal3s + glNormal3sv + glNormalPointer + glOrtho + glPassThrough + glPixelMapfv + glPixelMapuiv + glPixelMapusv + glPixelStoref + glPixelStorei + glPixelTransferf + glPixelTransferi + glPixelZoom + glPointSize + glPolygonMode + glPolygonOffset + glPolygonStipple + glPopAttrib + glPopClientAttrib + glPopMatrix + glPopName + glPrioritizeTextures + glPushAttrib + glPushClientAttrib + glPushMatrix + glPushName + glRasterPos2d + glRasterPos2dv + glRasterPos2f + glRasterPos2fv + glRasterPos2i + glRasterPos2iv + glRasterPos2s + glRasterPos2sv + glRasterPos3d + glRasterPos3dv + glRasterPos3f + glRasterPos3fv + glRasterPos3i + glRasterPos3iv + glRasterPos3s + glRasterPos3sv + glRasterPos4d + glRasterPos4dv + glRasterPos4f + glRasterPos4fv + glRasterPos4i + glRasterPos4iv + glRasterPos4s + glRasterPos4sv + glReadBuffer + glReadPixels + glRectd + glRectdv + glRectf + glRectfv + glRecti + glRectiv + glRects + glRectsv + glRenderMode + glRotated + glRotatef + glScaled + glScalef + glScissor + glSelectBuffer + glShadeModel + glStencilFunc + glStencilMask + glStencilOp + glTexCoord1d + glTexCoord1dv + glTexCoord1f + glTexCoord1fv + glTexCoord1i + glTexCoord1iv + glTexCoord1s + glTexCoord1sv + glTexCoord2d + glTexCoord2dv + glTexCoord2f + glTexCoord2fv + glTexCoord2i + glTexCoord2iv + glTexCoord2s + glTexCoord2sv + glTexCoord3d + glTexCoord3dv + glTexCoord3f + glTexCoord3fv + glTexCoord3i + glTexCoord3iv + glTexCoord3s + glTexCoord3sv + glTexCoord4d + glTexCoord4dv + glTexCoord4f + glTexCoord4fv + glTexCoord4i + glTexCoord4iv + glTexCoord4s + glTexCoord4sv + glTexCoordPointer + glTexEnvf + glTexEnvfv + glTexEnvi + glTexEnviv + glTexGend + glTexGendv + glTexGenf + glTexGenfv + glTexGeni + glTexGeniv + glTexImage1D + glTexImage2D + glTexParameterf + glTexParameterfv + glTexParameteri + glTexParameteriv + glTexSubImage1D + glTexSubImage2D + glTranslated + glTranslatef + glVertex2d + glVertex2dv + glVertex2f + glVertex2fv + glVertex2i + glVertex2iv + glVertex2s + glVertex2sv + glVertex3d + glVertex3dv + glVertex3f + glVertex3fv + glVertex3i + glVertex3iv + glVertex3s + glVertex3sv + glVertex4d + glVertex4dv + glVertex4f + glVertex4fv + glVertex4i + glVertex4iv + glVertex4s + glVertex4sv + glVertexPointer + glViewport + wglChoosePixelFormat + wglCopyContext + wglCreateContext + wglCreateLayerContext + wglDeleteContext + wglDescribeLayerPlane + wglDescribePixelFormat + wglGetCurrentContext + wglGetCurrentDC +; wglGetDefaultProcAddress + wglGetLayerPaletteEntries + wglGetPixelFormat + wglGetProcAddress + wglMakeCurrent + wglRealizeLayerPalette + wglSetLayerPaletteEntries + wglSetPixelFormat + wglShareLists + wglSwapBuffers + wglSwapLayerBuffers +; wglSwapMultipleBuffers + wglUseFontBitmapsA + wglUseFontBitmapsW + wglUseFontOutlinesA + wglUseFontOutlinesW + wglGetExtensionsStringARB + DrvCopyContext + DrvCreateContext + DrvCreateLayerContext + DrvDeleteContext + DrvDescribeLayerPlane + DrvDescribePixelFormat + DrvGetLayerPaletteEntries + DrvGetProcAddress + DrvRealizeLayerPalette + DrvReleaseContext + DrvSetCallbackProcs + DrvSetContext + DrvSetLayerPaletteEntries + DrvSetPixelFormat + DrvShareLists + DrvSwapBuffers + DrvSwapLayerBuffers + DrvValidateVersion diff --git a/src/gallium/state_trackers/wgl/shared/stw_arbextensionsstring.c b/src/gallium/state_trackers/wgl/shared/stw_arbextensionsstring.c new file mode 100644 index 00000000000..b3934cb4643 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_arbextensionsstring.c @@ -0,0 +1,42 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <windows.h> + +#include "stw_arbextensionsstring.h" + +WINGDIAPI const char * APIENTRY +wglGetExtensionsStringARB( + HDC hdc ) +{ + (void) hdc; + + return + "WGL_ARB_extensions_string " + "WGL_ARB_multisample " + "WGL_ARB_pixel_format"; +} diff --git a/src/gallium/state_trackers/wgl/shared/stw_arbextensionsstring.h b/src/gallium/state_trackers/wgl/shared/stw_arbextensionsstring.h new file mode 100644 index 00000000000..a0e4c5d98e8 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_arbextensionsstring.h @@ -0,0 +1,35 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef WGL_ARBEXTENSIONSSTRING_H +#define WGL_ARBEXTENSIONSSTRING_H + +WINGDIAPI const char * APIENTRY +wglGetExtensionsStringARB( + HDC hdc ); + +#endif /* WGL_ARBEXTENSIONSSTRING_H */ diff --git a/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c b/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c new file mode 100644 index 00000000000..f5636354202 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.c @@ -0,0 +1,519 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <windows.h> + +#include "pipe/p_compiler.h" +#include "util/u_memory.h" +#include "stw_public.h" +#include "stw_pixelformat.h" +#include "stw_arbpixelformat.h" + +#define WGL_NUMBER_PIXEL_FORMATS_ARB 0x2000 +#define WGL_DRAW_TO_WINDOW_ARB 0x2001 +#define WGL_DRAW_TO_BITMAP_ARB 0x2002 +#define WGL_ACCELERATION_ARB 0x2003 +#define WGL_NEED_PALETTE_ARB 0x2004 +#define WGL_NEED_SYSTEM_PALETTE_ARB 0x2005 +#define WGL_SWAP_LAYER_BUFFERS_ARB 0x2006 +#define WGL_SWAP_METHOD_ARB 0x2007 +#define WGL_NUMBER_OVERLAYS_ARB 0x2008 +#define WGL_NUMBER_UNDERLAYS_ARB 0x2009 +#define WGL_TRANSPARENT_ARB 0x200A +#define WGL_TRANSPARENT_RED_VALUE_ARB 0x2037 +#define WGL_TRANSPARENT_GREEN_VALUE_ARB 0x2038 +#define WGL_TRANSPARENT_BLUE_VALUE_ARB 0x2039 +#define WGL_TRANSPARENT_ALPHA_VALUE_ARB 0x203A +#define WGL_TRANSPARENT_INDEX_VALUE_ARB 0x203B +#define WGL_SHARE_DEPTH_ARB 0x200C +#define WGL_SHARE_STENCIL_ARB 0x200D +#define WGL_SHARE_ACCUM_ARB 0x200E +#define WGL_SUPPORT_GDI_ARB 0x200F +#define WGL_SUPPORT_OPENGL_ARB 0x2010 +#define WGL_DOUBLE_BUFFER_ARB 0x2011 +#define WGL_STEREO_ARB 0x2012 +#define WGL_PIXEL_TYPE_ARB 0x2013 +#define WGL_COLOR_BITS_ARB 0x2014 +#define WGL_RED_BITS_ARB 0x2015 +#define WGL_RED_SHIFT_ARB 0x2016 +#define WGL_GREEN_BITS_ARB 0x2017 +#define WGL_GREEN_SHIFT_ARB 0x2018 +#define WGL_BLUE_BITS_ARB 0x2019 +#define WGL_BLUE_SHIFT_ARB 0x201A +#define WGL_ALPHA_BITS_ARB 0x201B +#define WGL_ALPHA_SHIFT_ARB 0x201C +#define WGL_ACCUM_BITS_ARB 0x201D +#define WGL_ACCUM_RED_BITS_ARB 0x201E +#define WGL_ACCUM_GREEN_BITS_ARB 0x201F +#define WGL_ACCUM_BLUE_BITS_ARB 0x2020 +#define WGL_ACCUM_ALPHA_BITS_ARB 0x2021 +#define WGL_DEPTH_BITS_ARB 0x2022 +#define WGL_STENCIL_BITS_ARB 0x2023 +#define WGL_AUX_BUFFERS_ARB 0x2024 + +#define WGL_NO_ACCELERATION_ARB 0x2025 +#define WGL_GENERIC_ACCELERATION_ARB 0x2026 +#define WGL_FULL_ACCELERATION_ARB 0x2027 + +#define WGL_SWAP_EXCHANGE_ARB 0x2028 +#define WGL_SWAP_COPY_ARB 0x2029 +#define WGL_SWAP_UNDEFINED_ARB 0x202A + +#define WGL_TYPE_RGBA_ARB 0x202B +#define WGL_TYPE_COLORINDEX_ARB 0x202C + +/* From arb_multisample: + */ +#define WGL_SAMPLE_BUFFERS_ARB 0x2041 +#define WGL_SAMPLES_ARB 0x2042 + + +static boolean +query_attrib( + int iPixelFormat, + int iLayerPlane, + int attrib, + int *pvalue ) +{ + uint count; + uint index; + const struct pixelformat_info *pf; + + count = pixelformat_get_extended_count(); + + if (attrib == WGL_NUMBER_PIXEL_FORMATS_ARB) { + *pvalue = (int) count; + return TRUE; + } + + index = (uint) iPixelFormat - 1; + if (index >= count) + return FALSE; + + pf = pixelformat_get_info( index ); + + switch (attrib) { + case WGL_DRAW_TO_WINDOW_ARB: + *pvalue = TRUE; + return TRUE; + + case WGL_DRAW_TO_BITMAP_ARB: + *pvalue = FALSE; + return TRUE; + + case WGL_NEED_PALETTE_ARB: + *pvalue = FALSE; + return TRUE; + + case WGL_NEED_SYSTEM_PALETTE_ARB: + *pvalue = FALSE; + return TRUE; + + case WGL_SWAP_METHOD_ARB: + if (pf->flags & PF_FLAG_DOUBLEBUFFER) + *pvalue = WGL_SWAP_COPY_ARB; + else + *pvalue = WGL_SWAP_UNDEFINED_ARB; + return TRUE; + + case WGL_SWAP_LAYER_BUFFERS_ARB: + *pvalue = FALSE; + return TRUE; + + case WGL_NUMBER_OVERLAYS_ARB: + *pvalue = 0; + return TRUE; + + case WGL_NUMBER_UNDERLAYS_ARB: + *pvalue = 0; + return TRUE; + } + + if (iLayerPlane != 0) + return FALSE; + + switch (attrib) { + case WGL_ACCELERATION_ARB: + *pvalue = WGL_FULL_ACCELERATION_ARB; + break; + + case WGL_TRANSPARENT_ARB: + *pvalue = FALSE; + break; + + case WGL_TRANSPARENT_RED_VALUE_ARB: + case WGL_TRANSPARENT_GREEN_VALUE_ARB: + case WGL_TRANSPARENT_BLUE_VALUE_ARB: + case WGL_TRANSPARENT_ALPHA_VALUE_ARB: + case WGL_TRANSPARENT_INDEX_VALUE_ARB: + break; + + case WGL_SHARE_DEPTH_ARB: + case WGL_SHARE_STENCIL_ARB: + case WGL_SHARE_ACCUM_ARB: + *pvalue = TRUE; + break; + + case WGL_SUPPORT_GDI_ARB: + *pvalue = FALSE; + break; + + case WGL_SUPPORT_OPENGL_ARB: + *pvalue = TRUE; + break; + + case WGL_DOUBLE_BUFFER_ARB: + if (pf->flags & PF_FLAG_DOUBLEBUFFER) + *pvalue = TRUE; + else + *pvalue = FALSE; + break; + + case WGL_STEREO_ARB: + *pvalue = FALSE; + break; + + case WGL_PIXEL_TYPE_ARB: + *pvalue = WGL_TYPE_RGBA_ARB; + break; + + case WGL_COLOR_BITS_ARB: + *pvalue = (int) (pf->color.redbits + pf->color.greenbits + pf->color.bluebits); + break; + + case WGL_RED_BITS_ARB: + *pvalue = (int) pf->color.redbits; + break; + + case WGL_RED_SHIFT_ARB: + *pvalue = (int) pf->color.redshift; + break; + + case WGL_GREEN_BITS_ARB: + *pvalue = (int) pf->color.greenbits; + break; + + case WGL_GREEN_SHIFT_ARB: + *pvalue = (int) pf->color.greenshift; + break; + + case WGL_BLUE_BITS_ARB: + *pvalue = (int) pf->color.bluebits; + break; + + case WGL_BLUE_SHIFT_ARB: + *pvalue = (int) pf->color.blueshift; + break; + + case WGL_ALPHA_BITS_ARB: + *pvalue = (int) pf->alpha.alphabits; + break; + + case WGL_ALPHA_SHIFT_ARB: + *pvalue = (int) pf->alpha.alphashift; + break; + + case WGL_ACCUM_BITS_ARB: + case WGL_ACCUM_RED_BITS_ARB: + case WGL_ACCUM_GREEN_BITS_ARB: + case WGL_ACCUM_BLUE_BITS_ARB: + case WGL_ACCUM_ALPHA_BITS_ARB: + *pvalue = 0; + break; + + case WGL_DEPTH_BITS_ARB: + *pvalue = (int) pf->depth.depthbits; + break; + + case WGL_STENCIL_BITS_ARB: + *pvalue = (int) pf->depth.stencilbits; + break; + + case WGL_AUX_BUFFERS_ARB: + *pvalue = 0; + break; + + case WGL_SAMPLE_BUFFERS_ARB: + if (pf->flags & PF_FLAG_MULTISAMPLED) + *pvalue = stw_query_sample_buffers(); + else + *pvalue = 0; + break; + + case WGL_SAMPLES_ARB: + if (pf->flags & PF_FLAG_MULTISAMPLED) + *pvalue = stw_query_samples(); + else + *pvalue = 0; + break; + + default: + return FALSE; + } + + return TRUE; +} + +struct attrib_match_info +{ + int attribute; + int weight; + BOOL exact; +}; + +static struct attrib_match_info attrib_match[] = { + + /* WGL_ARB_pixel_format */ + { WGL_DRAW_TO_WINDOW_ARB, 0, TRUE }, + { WGL_DRAW_TO_BITMAP_ARB, 0, TRUE }, + { WGL_ACCELERATION_ARB, 0, TRUE }, + { WGL_NEED_PALETTE_ARB, 0, TRUE }, + { WGL_NEED_SYSTEM_PALETTE_ARB, 0, TRUE }, + { WGL_SWAP_LAYER_BUFFERS_ARB, 0, TRUE }, + { WGL_SWAP_METHOD_ARB, 0, TRUE }, + { WGL_NUMBER_OVERLAYS_ARB, 4, FALSE }, + { WGL_NUMBER_UNDERLAYS_ARB, 4, FALSE }, + /*{ WGL_SHARE_DEPTH_ARB, 0, TRUE },*/ /* no overlays -- ignore */ + /*{ WGL_SHARE_STENCIL_ARB, 0, TRUE },*/ /* no overlays -- ignore */ + /*{ WGL_SHARE_ACCUM_ARB, 0, TRUE },*/ /* no overlays -- ignore */ + { WGL_SUPPORT_GDI_ARB, 0, TRUE }, + { WGL_SUPPORT_OPENGL_ARB, 0, TRUE }, + { WGL_DOUBLE_BUFFER_ARB, 0, TRUE }, + { WGL_STEREO_ARB, 0, TRUE }, + { WGL_PIXEL_TYPE_ARB, 0, TRUE }, + { WGL_COLOR_BITS_ARB, 1, FALSE }, + { WGL_RED_BITS_ARB, 1, FALSE }, + { WGL_GREEN_BITS_ARB, 1, FALSE }, + { WGL_BLUE_BITS_ARB, 1, FALSE }, + { WGL_ALPHA_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_RED_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_GREEN_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_BLUE_BITS_ARB, 1, FALSE }, + { WGL_ACCUM_ALPHA_BITS_ARB, 1, FALSE }, + { WGL_DEPTH_BITS_ARB, 1, FALSE }, + { WGL_STENCIL_BITS_ARB, 1, FALSE }, + { WGL_AUX_BUFFERS_ARB, 2, FALSE }, + + /* WGL_ARB_multisample */ + { WGL_SAMPLE_BUFFERS_ARB, 2, FALSE }, + { WGL_SAMPLES_ARB, 2, FALSE } +}; + +struct pixelformat_score +{ + int points; + uint index; +}; + +static BOOL +score_pixelformats( + struct pixelformat_score *scores, + uint count, + int attribute, + int expected_value ) +{ + uint i; + struct attrib_match_info *ami = NULL; + uint index; + + /* Find out if a given attribute should be considered for score calculation. + */ + for (i = 0; i < sizeof( attrib_match ) / sizeof( attrib_match[0] ); i++) { + if (attrib_match[i].attribute == attribute) { + ami = &attrib_match[i]; + break; + } + } + if (ami == NULL) + return TRUE; + + /* Iterate all pixelformats, query the requested attribute and calculate + * score points. + */ + for (index = 0; index < count; index++) { + int actual_value; + + if (!query_attrib( index + 1, 0, attribute, &actual_value )) + return FALSE; + + if (ami->exact) { + /* For an exact match criteria, if the actual and expected values differ, + * the score is set to 0 points, effectively removing the pixelformat + * from a list of matching pixelformats. + */ + if (actual_value != expected_value) + scores[index].points = 0; + } + else { + /* For a minimum match criteria, if the actual value is smaller than the expected + * value, the pixelformat is rejected (score set to 0). However, if the actual + * value is bigger, the pixelformat is given a penalty to favour pixelformats that + * more closely match the expected values. + */ + if (actual_value < expected_value) + scores[index].points = 0; + else if (actual_value > expected_value) + scores[index].points -= (actual_value - expected_value) * ami->weight; + } + } + + return TRUE; +} + +WINGDIAPI BOOL APIENTRY +wglChoosePixelFormatARB( + HDC hdc, + const int *piAttribIList, + const FLOAT *pfAttribFList, + UINT nMaxFormats, + int *piFormats, + UINT *nNumFormats ) +{ + uint count; + struct pixelformat_score *scores; + uint i; + + *nNumFormats = 0; + + /* Allocate and initialize pixelformat score table -- better matches + * have higher scores. Start with a high score and take out penalty + * points for a mismatch when the match does not have to be exact. + * Set a score to 0 if there is a mismatch for an exact match criteria. + */ + count = pixelformat_get_extended_count(); + scores = (struct pixelformat_score *) MALLOC( count * sizeof( struct pixelformat_score ) ); + if (scores == NULL) + return FALSE; + for (i = 0; i < count; i++) { + scores[i].points = 0x7fffffff; + scores[i].index = i; + } + + /* Given the attribute list calculate a score for each pixelformat. + */ + if (piAttribIList != NULL) { + while (*piAttribIList != 0) { + if (!score_pixelformats( scores, count, piAttribIList[0], piAttribIList[1] )) { + FREE( scores ); + return FALSE; + } + piAttribIList += 2; + } + } + if (pfAttribFList != NULL) { + while (*pfAttribFList != 0) { + if (!score_pixelformats( scores, count, (int) pfAttribFList[0], (int) pfAttribFList[1] )) { + FREE( scores ); + return FALSE; + } + pfAttribFList += 2; + } + } + + /* Bubble-sort the resulting scores. Pixelformats with higher scores go first. + * TODO: Find out if there are any patent issues with it. + */ + if (count > 1) { + uint n = count; + boolean swapped; + + do { + swapped = FALSE; + for (i = 1; i < n; i++) { + if (scores[i - 1].points < scores[i].points) { + struct pixelformat_score score = scores[i - 1]; + + scores[i - 1] = scores[i]; + scores[i] = score; + swapped = TRUE; + } + } + n--; + } + while (swapped); + } + + /* Return a list of pixelformats that are the best match. + * Reject pixelformats with non-positive scores. + */ + for (i = 0; i < count; i++) { + if (scores[i].points > 0) { + if (*nNumFormats < nMaxFormats) + piFormats[*nNumFormats] = scores[i].index + 1; + (*nNumFormats)++; + } + } + + FREE( scores ); + return TRUE; +} + +WINGDIAPI BOOL APIENTRY +wglGetPixelFormatAttribfvARB( + HDC hdc, + int iPixelFormat, + int iLayerPlane, + UINT nAttributes, + const int *piAttributes, + FLOAT *pfValues ) +{ + UINT i; + + (void) hdc; + + for (i = 0; i < nAttributes; i++) { + int value; + + if (!query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &value )) + return FALSE; + pfValues[i] = (FLOAT) value; + } + + return TRUE; +} + +WINGDIAPI BOOL APIENTRY +wglGetPixelFormatAttribivARB( + HDC hdc, + int iPixelFormat, + int iLayerPlane, + UINT nAttributes, + const int *piAttributes, + int *piValues ) +{ + UINT i; + + (void) hdc; + + for (i = 0; i < nAttributes; i++) { + if (!query_attrib( iPixelFormat, iLayerPlane, piAttributes[i], &piValues[i] )) + return FALSE; + } + + return TRUE; +} diff --git a/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.h b/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.h new file mode 100644 index 00000000000..a6c42599424 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_arbpixelformat.h @@ -0,0 +1,61 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef WGL_ARBPIXELFORMAT_H +#define WGL_ARBPIXELFORMAT_H + + +/* Extension functions for get_proc_address: + */ +WINGDIAPI BOOL APIENTRY +wglChoosePixelFormatARB( + HDC hdc, + const int *piAttribIList, + const FLOAT *pfAttribFList, + UINT nMaxFormats, + int *piFormats, + UINT *nNumFormats ); + +WINGDIAPI BOOL APIENTRY +wglGetPixelFormatAttribfvARB( + HDC hdc, + int iPixelFormat, + int iLayerPlane, + UINT nAttributes, + const int *piAttributes, + FLOAT *pfValues ); + +WINGDIAPI BOOL APIENTRY +wglGetPixelFormatAttribivARB( + HDC hdc, + int iPixelFormat, + int iLayerPlane, + UINT nAttributes, + const int *piAttributes, + int *piValues ); + +#endif /* WGL_ARBPIXELFORMAT_H */ diff --git a/src/gallium/state_trackers/wgl/shared/stw_context.c b/src/gallium/state_trackers/wgl/shared/stw_context.c new file mode 100644 index 00000000000..2abf97b5adb --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_context.c @@ -0,0 +1,292 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <windows.h> + +#include "main/mtypes.h" +#include "main/context.h" +#include "pipe/p_compiler.h" +#include "pipe/p_context.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_public.h" +#include "shared/stw_device.h" +#include "shared/stw_winsys.h" +#include "shared/stw_framebuffer.h" +#include "shared/stw_pixelformat.h" +#include "stw_public.h" +#include "stw_context.h" + +static struct stw_context *ctx_head = NULL; + +static HDC current_hdc = NULL; +static struct stw_context *current_hrc = NULL; + +BOOL +stw_copy_context( + struct stw_context *src, + struct stw_context *dst, + UINT mask ) +{ + (void) src; + (void) dst; + (void) mask; + + return FALSE; +} + +struct stw_context * +stw_create_context( + HDC hdc, + int iLayerPlane ) +{ + uint pfi; + const struct pixelformat_info *pf = NULL; + struct stw_context *ctx = NULL; + GLvisual *visual = NULL; + struct pipe_context *pipe = NULL; + + if (iLayerPlane != 0) + return NULL; + + pfi = stw_pixelformat_get( hdc ); + if (pfi == 0) + return NULL; + + pf = pixelformat_get_info( pfi - 1 ); + + ctx = CALLOC_STRUCT( stw_context ); + if (ctx == NULL) + return NULL; + + ctx->hdc = hdc; + ctx->color_bits = GetDeviceCaps( ctx->hdc, BITSPIXEL ); + + /* Create visual based on flags + */ + visual = _mesa_create_visual( + GL_TRUE, + (pf->flags & PF_FLAG_DOUBLEBUFFER) ? GL_TRUE : GL_FALSE, + GL_FALSE, + pf->color.redbits, + pf->color.greenbits, + pf->color.bluebits, + pf->alpha.alphabits, + 0, + pf->depth.depthbits, + pf->depth.stencilbits, + 0, + 0, + 0, + 0, + (pf->flags & PF_FLAG_MULTISAMPLED) ? stw_query_samples() : 0 ); + if (visual == NULL) + goto fail; + + pipe = stw_dev->stw_winsys->create_context( stw_dev->screen ); + if (pipe == NULL) + goto fail; + + assert(!pipe->priv); + pipe->priv = hdc; + + ctx->st = st_create_context( pipe, visual, NULL ); + if (ctx->st == NULL) + goto fail; + + ctx->st->ctx->DriverCtx = ctx; + + ctx->next = ctx_head; + ctx_head = ctx; + + return ctx; + +fail: + if (visual) + _mesa_destroy_visual( visual ); + + if (pipe) + pipe->destroy( pipe ); + + FREE( ctx ); + return NULL; +} + + +BOOL +stw_delete_context( + struct stw_context *hglrc ) +{ + struct stw_context **link = &ctx_head; + struct stw_context *ctx = ctx_head; + + while (ctx != NULL) { + if (ctx == hglrc) { + GLcontext *glctx = ctx->st->ctx; + GET_CURRENT_CONTEXT( glcurctx ); + struct stw_framebuffer *fb; + + /* Unbind current if deleting current context. + */ + if (glcurctx == glctx) + st_make_current( NULL, NULL, NULL ); + + fb = framebuffer_from_hdc( ctx->hdc ); + if (fb) + framebuffer_destroy( fb ); + + if (WindowFromDC( ctx->hdc ) != NULL) + ReleaseDC( WindowFromDC( ctx->hdc ), ctx->hdc ); + + st_destroy_context( ctx->st ); + + *link = ctx->next; + FREE( ctx ); + return TRUE; + } + + link = &ctx->next; + ctx = ctx->next; + } + + return FALSE; +} + +/* Find the width and height of the window named by hdc. + */ +static void +get_window_size( HDC hdc, GLuint *width, GLuint *height ) +{ + if (WindowFromDC( hdc )) { + RECT rect; + + GetClientRect( WindowFromDC( hdc ), &rect ); + *width = rect.right - rect.left; + *height = rect.bottom - rect.top; + } + else { + *width = GetDeviceCaps( hdc, HORZRES ); + *height = GetDeviceCaps( hdc, VERTRES ); + } +} + +struct stw_context * +stw_get_current_context( void ) +{ + return current_hrc; +} + +HDC +stw_get_current_dc( void ) +{ + return current_hdc; +} + +BOOL +stw_make_current( + HDC hdc, + struct stw_context *hglrc ) +{ + struct stw_context *ctx = ctx_head; + GET_CURRENT_CONTEXT( glcurctx ); + struct stw_framebuffer *fb; + GLuint width = 0; + GLuint height = 0; + + current_hdc = hdc; + current_hrc = hglrc; + + if (hdc == NULL || hglrc == NULL) { + st_make_current( NULL, NULL, NULL ); + return TRUE; + } + + while (ctx != NULL) { + if (ctx == hglrc) + break; + ctx = ctx->next; + } + if (ctx == NULL) + return FALSE; + + /* Return if already current. + */ + if (glcurctx != NULL) { + struct stw_context *curctx = (struct stw_context *) glcurctx->DriverCtx; + + if (curctx != NULL && curctx == ctx && ctx->hdc == hdc) + return TRUE; + } + + fb = framebuffer_from_hdc( hdc ); + + if (hdc != NULL) + get_window_size( hdc, &width, &height ); + + /* Lazy creation of framebuffers. + */ + if (fb == NULL && ctx != NULL && hdc != NULL) { + GLvisual *visual = &ctx->st->ctx->Visual; + + fb = framebuffer_create( hdc, visual, width, height ); + if (fb == NULL) + return FALSE; + + fb->dib_hDC = CreateCompatibleDC( hdc ); + fb->hbmDIB = NULL; + fb->pbPixels = NULL; + } + + if (ctx && fb) { + st_make_current( ctx->st, fb->stfb, fb->stfb ); + framebuffer_resize( fb, width, height ); + ctx->hdc = hdc; + ctx->st->pipe->priv = hdc; + } + else { + /* Detach */ + st_make_current( NULL, NULL, NULL ); + } + + return TRUE; +} + +struct stw_context * +stw_context_from_hdc( + HDC hdc ) +{ + struct stw_context *ctx = ctx_head; + + while (ctx != NULL) { + if (ctx->hdc == hdc) + return ctx; + ctx = ctx->next; + } + return NULL; +} + + + diff --git a/src/gallium/state_trackers/wgl/shared/stw_context.h b/src/gallium/state_trackers/wgl/shared/stw_context.h new file mode 100644 index 00000000000..89a8f900d81 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_context.h @@ -0,0 +1,53 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_CONTEXT_H +#define STW_CONTEXT_H + +#include <windows.h> + +struct st_context; + +struct stw_context +{ + struct st_context *st; + HDC hdc; + DWORD color_bits; + struct stw_context *next; +}; + +struct stw_context * +stw_context_from_hdc(HDC hdc ); + + + + + + + + +#endif /* STW_CONTEXT_H */ diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.c b/src/gallium/state_trackers/wgl/shared/stw_device.c new file mode 100644 index 00000000000..6873e813ee3 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_device.c @@ -0,0 +1,91 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <windows.h> + +#include "pipe/p_debug.h" +#include "pipe/p_screen.h" + +#include "shared/stw_device.h" +#include "shared/stw_winsys.h" +#include "shared/stw_pixelformat.h" +#include "shared/stw_public.h" +#include "stw.h" + + +struct stw_device *stw_dev = NULL; + + +/** + * XXX: Dispatch pipe_screen::flush_front_buffer to our + * stw_winsys::flush_front_buffer. + */ +static void +st_flush_frontbuffer(struct pipe_screen *screen, + struct pipe_surface *surf, + void *context_private ) +{ + const struct stw_winsys *stw_winsys = stw_dev->stw_winsys; + HDC hdc = (HDC)context_private; + + stw_winsys->flush_frontbuffer(screen, surf, hdc); +} + + +boolean +stw_shared_init(const struct stw_winsys *stw_winsys) +{ + static struct stw_device stw_dev_storage; + + assert(!stw_dev); + + stw_dev = &stw_dev_storage; + memset(stw_dev, 0, sizeof(*stw_dev)); + + stw_dev->stw_winsys = stw_winsys; + + stw_dev->screen = stw_winsys->create_screen(); + if(!stw_dev->screen) + goto error1; + + stw_dev->screen->flush_frontbuffer = st_flush_frontbuffer; + + pixelformat_init(); + + return TRUE; + +error1: + stw_dev = NULL; + return FALSE; +} + + +void +stw_shared_cleanup(void) +{ + stw_dev = NULL; +} diff --git a/src/gallium/state_trackers/wgl/shared/stw_device.h b/src/gallium/state_trackers/wgl/shared/stw_device.h new file mode 100644 index 00000000000..bc0bce37c6e --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_device.h @@ -0,0 +1,44 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef ST_DEVICE_H_ +#define ST_DEVICE_H_ + + +struct pipe_screen; + +struct stw_device +{ + const struct stw_winsys *stw_winsys; + struct pipe_screen *screen; +}; + + +extern struct stw_device *stw_dev; + + +#endif /* ST_DEVICE_H_ */ diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c new file mode 100644 index 00000000000..c70b31a4881 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.c @@ -0,0 +1,212 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <windows.h> + +#include "main/context.h" +#include "pipe/p_format.h" +#include "pipe/p_screen.h" +#include "state_tracker/st_context.h" +#include "state_tracker/st_public.h" +#include "stw_framebuffer.h" +#include "stw_device.h" +#include "stw_public.h" +#include "stw_winsys.h" + + +void +framebuffer_resize( + struct stw_framebuffer *fb, + GLuint width, + GLuint height ) +{ + if (fb->hbmDIB == NULL || fb->stfb->Base.Width != width || fb->stfb->Base.Height != height) { + if (fb->hbmDIB) + DeleteObject( fb->hbmDIB ); + + fb->hbmDIB = CreateCompatibleBitmap( + fb->hDC, + width, + height ); + } + + st_resize_framebuffer( fb->stfb, width, height ); +} + +static struct stw_framebuffer *fb_head = NULL; + +static LRESULT CALLBACK +window_proc( + HWND hWnd, + UINT uMsg, + WPARAM wParam, + LPARAM lParam ) +{ + struct stw_framebuffer *fb; + + for (fb = fb_head; fb != NULL; fb = fb->next) + if (fb->hWnd == hWnd) + break; + assert( fb != NULL ); + + if (uMsg == WM_SIZE && wParam != SIZE_MINIMIZED) + framebuffer_resize( fb, LOWORD( lParam ), HIWORD( lParam ) ); + + return CallWindowProc( fb->WndProc, hWnd, uMsg, wParam, lParam ); +} + +/* Create a new framebuffer object which will correspond to the given HDC. + */ +struct stw_framebuffer * +framebuffer_create( + HDC hdc, + GLvisual *visual, + GLuint width, + GLuint height ) +{ + struct stw_framebuffer *fb; + enum pipe_format colorFormat, depthFormat, stencilFormat; + + fb = CALLOC_STRUCT( stw_framebuffer ); + if (fb == NULL) + return NULL; + + /* Determine PIPE_FORMATs for buffers. + */ + colorFormat = PIPE_FORMAT_A8R8G8B8_UNORM; + + if (visual->depthBits == 0) + depthFormat = PIPE_FORMAT_NONE; + else if (visual->depthBits <= 16) + depthFormat = PIPE_FORMAT_Z16_UNORM; + else if (visual->depthBits <= 24) + depthFormat = PIPE_FORMAT_S8Z24_UNORM; + else + depthFormat = PIPE_FORMAT_Z32_UNORM; + + if (visual->stencilBits == 8) { + if (depthFormat == PIPE_FORMAT_S8Z24_UNORM) + stencilFormat = depthFormat; + else + stencilFormat = PIPE_FORMAT_S8_UNORM; + } + else { + stencilFormat = PIPE_FORMAT_NONE; + } + + fb->stfb = st_create_framebuffer( + visual, + colorFormat, + depthFormat, + stencilFormat, + width, + height, + (void *) fb ); + + fb->cColorBits = GetDeviceCaps( hdc, BITSPIXEL ); + fb->hDC = hdc; + + /* Subclass a window associated with the device context. + */ + fb->hWnd = WindowFromDC( hdc ); + if (fb->hWnd != NULL) { + fb->WndProc = (WNDPROC) SetWindowLong( + fb->hWnd, + GWL_WNDPROC, + (LONG) window_proc ); + } + + fb->next = fb_head; + fb_head = fb; + return fb; +} + +void +framebuffer_destroy( + struct stw_framebuffer *fb ) +{ + struct stw_framebuffer **link = &fb_head; + struct stw_framebuffer *pfb = fb_head; + + while (pfb != NULL) { + if (pfb == fb) { + if (fb->hWnd != NULL) { + SetWindowLong( + fb->hWnd, + GWL_WNDPROC, + (LONG) fb->WndProc ); + } + + *link = fb->next; + FREE( fb ); + return; + } + + link = &pfb->next; + pfb = pfb->next; + } +} + +/* Given an hdc, return the corresponding stw_framebuffer. + */ +struct stw_framebuffer * +framebuffer_from_hdc( + HDC hdc ) +{ + struct stw_framebuffer *fb; + + for (fb = fb_head; fb != NULL; fb = fb->next) + if (fb->hDC == hdc) + return fb; + return NULL; +} + + +BOOL +stw_swap_buffers( + HDC hdc ) +{ + struct stw_framebuffer *fb; + struct pipe_surface *surf; + + fb = framebuffer_from_hdc( hdc ); + if (fb == NULL) + return FALSE; + + /* If we're swapping the buffer associated with the current context + * we have to flush any pending rendering commands first. + */ + st_notify_swapbuffers( fb->stfb ); + + st_get_framebuffer_surface( fb->stfb, ST_SURFACE_BACK_LEFT, &surf ); + + stw_dev->stw_winsys->flush_frontbuffer(stw_dev->screen, + surf, + hdc ); + + return TRUE; +} diff --git a/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h new file mode 100644 index 00000000000..2e16e421f2c --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_framebuffer.h @@ -0,0 +1,71 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_FRAMEBUFFER_H +#define STW_FRAMEBUFFER_H + +#include "main/mtypes.h" + +/* Windows framebuffer, derived from gl_framebuffer. + */ +struct stw_framebuffer +{ + struct st_framebuffer *stfb; + HDC hDC; + int pixelformat; + BYTE cColorBits; + HDC dib_hDC; + HBITMAP hbmDIB; + HBITMAP hOldBitmap; + PBYTE pbPixels; + HWND hWnd; + WNDPROC WndProc; + struct stw_framebuffer *next; +}; + +struct stw_framebuffer * +framebuffer_create( + HDC hdc, + GLvisual *visual, + GLuint width, + GLuint height ); + +void +framebuffer_destroy( + struct stw_framebuffer *fb ); + +void +framebuffer_resize( + struct stw_framebuffer *fb, + GLuint width, + GLuint height ); + +struct stw_framebuffer * +framebuffer_from_hdc( + HDC hdc ); + +#endif /* STW_FRAMEBUFFER_H */ diff --git a/src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c b/src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c new file mode 100644 index 00000000000..ac2d6fc2605 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_getprocaddress.c @@ -0,0 +1,71 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <windows.h> + +#include "glapi/glapi.h" +#include "stw_arbextensionsstring.h" +#include "stw_arbpixelformat.h" +#include "stw_public.h" + +struct extension_entry +{ + const char *name; + PROC proc; +}; + +#define EXTENTRY(P) { #P, (PROC) P } + +static struct extension_entry extension_entries[] = { + + /* WGL_ARB_extensions_string */ + EXTENTRY( wglGetExtensionsStringARB ), + + /* WGL_ARB_pixel_format */ + EXTENTRY( wglChoosePixelFormatARB ), + EXTENTRY( wglGetPixelFormatAttribfvARB ), + EXTENTRY( wglGetPixelFormatAttribivARB ), + + { NULL, NULL } +}; + +PROC +stw_get_proc_address( + LPCSTR lpszProc ) +{ + struct extension_entry *entry; + + PROC p = (PROC) _glapi_get_proc_address( (const char *) lpszProc ); + if (p) + return p; + + for (entry = extension_entries; entry->name; entry++) + if (strcmp( lpszProc, entry->name ) == 0) + return entry->proc; + + return NULL; +} diff --git a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c new file mode 100644 index 00000000000..84b7b287b91 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.c @@ -0,0 +1,286 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "pipe/p_debug.h" +#include "stw_pixelformat.h" +#include "stw_public.h" + +#define MAX_PIXELFORMATS 16 + +static struct pixelformat_info pixelformats[MAX_PIXELFORMATS]; +static uint pixelformat_count = 0; +static uint pixelformat_extended_count = 0; + +static uint currentpixelformat = 0; + + +static void +add_standard_pixelformats( + struct pixelformat_info **ppf, + uint flags ) +{ + struct pixelformat_info *pf = *ppf; + struct pixelformat_color_info color24 = { 8, 0, 8, 8, 8, 16 }; + struct pixelformat_alpha_info alpha8 = { 8, 24 }; + struct pixelformat_alpha_info noalpha = { 0, 0 }; + struct pixelformat_depth_info depth24s8 = { 24, 8 }; + struct pixelformat_depth_info depth16 = { 16, 0 }; + + pf->flags = PF_FLAG_DOUBLEBUFFER | flags; + pf->color = color24; + pf->alpha = alpha8; + pf->depth = depth16; + pf++; + + pf->flags = PF_FLAG_DOUBLEBUFFER | flags; + pf->color = color24; + pf->alpha = alpha8; + pf->depth = depth24s8; + pf++; + + pf->flags = PF_FLAG_DOUBLEBUFFER | flags; + pf->color = color24; + pf->alpha = noalpha; + pf->depth = depth16; + pf++; + + pf->flags = PF_FLAG_DOUBLEBUFFER | flags; + pf->color = color24; + pf->alpha = noalpha; + pf->depth = depth24s8; + pf++; + + pf->flags = flags; + pf->color = color24; + pf->alpha = noalpha; + pf->depth = depth16; + pf++; + + pf->flags = flags; + pf->color = color24; + pf->alpha = noalpha; + pf->depth = depth24s8; + pf++; + + *ppf = pf; +} + +void +pixelformat_init( void ) +{ + struct pixelformat_info *pf = pixelformats; + + add_standard_pixelformats( &pf, 0 ); + pixelformat_count = pf - pixelformats; + + add_standard_pixelformats( &pf, PF_FLAG_MULTISAMPLED ); + pixelformat_extended_count = pf - pixelformats; + + assert( pixelformat_extended_count <= MAX_PIXELFORMATS ); +} + +uint +pixelformat_get_count( void ) +{ + return pixelformat_count; +} + +uint +pixelformat_get_extended_count( void ) +{ + return pixelformat_extended_count; +} + +const struct pixelformat_info * +pixelformat_get_info( uint index ) +{ + assert( index < pixelformat_extended_count ); + + return &pixelformats[index]; +} + + +int +stw_pixelformat_describe( + HDC hdc, + int iPixelFormat, + UINT nBytes, + LPPIXELFORMATDESCRIPTOR ppfd ) +{ + uint count; + uint index; + const struct pixelformat_info *pf; + + (void) hdc; + + count = pixelformat_get_extended_count(); + index = (uint) iPixelFormat - 1; + + if (ppfd == NULL) + return count; + if (index >= count || nBytes != sizeof( PIXELFORMATDESCRIPTOR )) + return 0; + + pf = pixelformat_get_info( index ); + + ppfd->nSize = sizeof( PIXELFORMATDESCRIPTOR ); + ppfd->nVersion = 1; + ppfd->dwFlags = PFD_DRAW_TO_WINDOW | PFD_SUPPORT_OPENGL; + if (pf->flags & PF_FLAG_DOUBLEBUFFER) + ppfd->dwFlags |= PFD_DOUBLEBUFFER | PFD_SWAP_COPY; + ppfd->iPixelType = PFD_TYPE_RGBA; + ppfd->cColorBits = pf->color.redbits + pf->color.greenbits + pf->color.bluebits; + ppfd->cRedBits = pf->color.redbits; + ppfd->cRedShift = pf->color.redshift; + ppfd->cGreenBits = pf->color.greenbits; + ppfd->cGreenShift = pf->color.greenshift; + ppfd->cBlueBits = pf->color.bluebits; + ppfd->cBlueShift = pf->color.blueshift; + ppfd->cAlphaBits = pf->alpha.alphabits; + ppfd->cAlphaShift = pf->alpha.alphashift; + ppfd->cAccumBits = 0; + ppfd->cAccumRedBits = 0; + ppfd->cAccumGreenBits = 0; + ppfd->cAccumBlueBits = 0; + ppfd->cAccumAlphaBits = 0; + ppfd->cDepthBits = pf->depth.depthbits; + ppfd->cStencilBits = pf->depth.stencilbits; + ppfd->cAuxBuffers = 0; + ppfd->iLayerType = 0; + ppfd->bReserved = 0; + ppfd->dwLayerMask = 0; + ppfd->dwVisibleMask = 0; + ppfd->dwDamageMask = 0; + + return count; +} + +/* Only used by the wgl code, but have it here to avoid exporting the + * pixelformat.h functionality. + */ +int stw_pixelformat_choose( HDC hdc, + CONST PIXELFORMATDESCRIPTOR *ppfd ) +{ + uint count; + uint index; + uint bestindex; + uint bestdelta; + + (void) hdc; + + count = pixelformat_get_count(); + bestindex = count; + bestdelta = 0xffffffff; + + for (index = 0; index < count; index++) { + uint delta = 0; + const struct pixelformat_info *pf = pixelformat_get_info( index ); + + if (!(ppfd->dwFlags & PFD_DOUBLEBUFFER_DONTCARE) && + !!(ppfd->dwFlags & PFD_DOUBLEBUFFER) != + !!(pf->flags & PF_FLAG_DOUBLEBUFFER)) + continue; + + if (ppfd->cColorBits != pf->color.redbits + pf->color.greenbits + pf->color.bluebits) + delta += 8; + + if (ppfd->cDepthBits != pf->depth.depthbits) + delta += 4; + + if (ppfd->cStencilBits != pf->depth.stencilbits) + delta += 2; + + if (ppfd->cAlphaBits != pf->alpha.alphabits) + delta++; + + if (delta < bestdelta) { + bestindex = index; + bestdelta = delta; + if (bestdelta == 0) + break; + } + } + + if (bestindex == count) + return 0; + + return bestindex + 1; +} + + +int +stw_pixelformat_get( + HDC hdc ) +{ + return currentpixelformat; +} + + +BOOL +stw_pixelformat_set( + HDC hdc, + int iPixelFormat ) +{ + uint count; + uint index; + + (void) hdc; + + index = (uint) iPixelFormat - 1; + count = pixelformat_get_extended_count(); + if (index >= count) + return FALSE; + + currentpixelformat = iPixelFormat; + + /* Some applications mistakenly use the undocumented wglSetPixelFormat + * function instead of SetPixelFormat, so we call SetPixelFormat here to + * avoid opengl32.dll's wglCreateContext to fail */ + if (GetPixelFormat(hdc) == 0) { + SetPixelFormat(hdc, iPixelFormat, NULL); + } + + return TRUE; +} + + + +/* XXX: this needs to be turned into queries on pipe_screen or + * stw_winsys. + */ +int +stw_query_sample_buffers( void ) +{ + return 1; +} + +int +stw_query_samples( void ) +{ + return 4; +} + diff --git a/src/gallium/state_trackers/wgl/shared/stw_pixelformat.h b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.h new file mode 100644 index 00000000000..7ca4194a2ae --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_pixelformat.h @@ -0,0 +1,83 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef PIXELFORMAT_H +#define PIXELFORMAT_H + +#include <windows.h> +#include "pipe/p_compiler.h" + +#define PF_FLAG_DOUBLEBUFFER 0x00000001 +#define PF_FLAG_MULTISAMPLED 0x00000002 + +struct pixelformat_color_info +{ + uint redbits; + uint redshift; + uint greenbits; + uint greenshift; + uint bluebits; + uint blueshift; +}; + +struct pixelformat_alpha_info +{ + uint alphabits; + uint alphashift; +}; + +struct pixelformat_depth_info +{ + uint depthbits; + uint stencilbits; +}; + +struct pixelformat_info +{ + uint flags; + struct pixelformat_color_info color; + struct pixelformat_alpha_info alpha; + struct pixelformat_depth_info depth; +}; + +void +pixelformat_init( void ); + +uint +pixelformat_get_count( void ); + +uint +pixelformat_get_extended_count( void ); + +const struct pixelformat_info * +pixelformat_get_info( uint index ); + +int stw_query_sample_buffers( void ); +int stw_query_samples( void ); + + +#endif /* PIXELFORMAT_H */ diff --git a/src/gallium/state_trackers/wgl/shared/stw_public.h b/src/gallium/state_trackers/wgl/shared/stw_public.h new file mode 100644 index 00000000000..75b504a50f6 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_public.h @@ -0,0 +1,75 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_PUBLIC_H +#define STW_PUBLIC_H + +#include <windows.h> +#include "pipe/p_compiler.h" + +struct stw_winsys; +struct stw_context; + +boolean +st_shared_init(const struct stw_winsys *stw_winsys); + +void +st_shared_cleanup(void); + + +BOOL stw_copy_context( struct stw_context *src, + struct stw_context *dst, + UINT mask ); + +struct stw_context *stw_create_context( HDC hdc, int iLayerPlane ); + +BOOL stw_delete_context( struct stw_context *ctx ); + +struct stw_context *stw_get_current_context( void ); + +HDC stw_get_current_dc( void ); + +BOOL stw_make_current( HDC hdc, struct stw_context *ctx ); + +BOOL stw_swap_buffers( HDC hdc ); + +PROC stw_get_proc_address( LPCSTR lpszProc ); + +int stw_pixelformat_describe( HDC hdc, + int iPixelFormat, + UINT nBytes, + LPPIXELFORMATDESCRIPTOR ppfd ); + +int stw_pixelformat_get( HDC hdc ); + +BOOL stw_pixelformat_set( HDC hdc, + int iPixelFormat ); + +int stw_pixelformat_choose( HDC hdc, + CONST PIXELFORMATDESCRIPTOR *ppfd ); + +#endif diff --git a/src/gallium/state_trackers/wgl/shared/stw_quirks.c b/src/gallium/state_trackers/wgl/shared/stw_quirks.c new file mode 100644 index 00000000000..0961ce3bb0e --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_quirks.c @@ -0,0 +1,113 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +/** + * @file + * + * This is hopefully a temporary hack to define some needed dispatch + * table entries. Hopefully, I'll find a better solution. The + * dispatch table generation scripts ought to be making these dummy + * stubs as well. + */ + +void gl_dispatch_stub_543(void){} +void gl_dispatch_stub_544(void){} +void gl_dispatch_stub_545(void){} +void gl_dispatch_stub_546(void){} +void gl_dispatch_stub_547(void){} +void gl_dispatch_stub_548(void){} +void gl_dispatch_stub_549(void){} +void gl_dispatch_stub_550(void){} +void gl_dispatch_stub_551(void){} +void gl_dispatch_stub_552(void){} +void gl_dispatch_stub_553(void){} +void gl_dispatch_stub_554(void){} +void gl_dispatch_stub_555(void){} +void gl_dispatch_stub_556(void){} +void gl_dispatch_stub_557(void){} +void gl_dispatch_stub_558(void){} +void gl_dispatch_stub_559(void){} +void gl_dispatch_stub_560(void){} +void gl_dispatch_stub_561(void){} +void gl_dispatch_stub_565(void){} +void gl_dispatch_stub_566(void){} +void gl_dispatch_stub_570(void){} +void gl_dispatch_stub_577(void){} +void gl_dispatch_stub_578(void){} +void gl_dispatch_stub_582(void){} +void gl_dispatch_stub_603(void){} +void gl_dispatch_stub_607(void){} +void gl_dispatch_stub_645(void){} +void gl_dispatch_stub_646(void){} +void gl_dispatch_stub_647(void){} +void gl_dispatch_stub_648(void){} +void gl_dispatch_stub_649(void){} +void gl_dispatch_stub_650(void){} +void gl_dispatch_stub_651(void){} +void gl_dispatch_stub_652(void){} +void gl_dispatch_stub_653(void){} +void gl_dispatch_stub_657(void){} +void gl_dispatch_stub_733(void){} +void gl_dispatch_stub_734(void){} +void gl_dispatch_stub_735(void){} +void gl_dispatch_stub_736(void){} +void gl_dispatch_stub_737(void){} +void gl_dispatch_stub_738(void){} +void gl_dispatch_stub_744(void){} +void gl_dispatch_stub_745(void){} +void gl_dispatch_stub_746(void){} +void gl_dispatch_stub_760(void){} +void gl_dispatch_stub_761(void){} +void gl_dispatch_stub_763(void){} +void gl_dispatch_stub_764(void){} +void gl_dispatch_stub_765(void){} +void gl_dispatch_stub_766(void){} +void gl_dispatch_stub_767(void){} +void gl_dispatch_stub_768(void){} + +void gl_dispatch_stub_562(void){} +void gl_dispatch_stub_563(void){} +void gl_dispatch_stub_564(void){} +void gl_dispatch_stub_567(void){} +void gl_dispatch_stub_568(void){} +void gl_dispatch_stub_569(void){} +void gl_dispatch_stub_580(void){} +void gl_dispatch_stub_581(void){} +void gl_dispatch_stub_606(void){} +void gl_dispatch_stub_654(void){} +void gl_dispatch_stub_655(void){} +void gl_dispatch_stub_656(void){} +void gl_dispatch_stub_739(void){} +void gl_dispatch_stub_740(void){} +void gl_dispatch_stub_741(void){} +void gl_dispatch_stub_748(void){} +void gl_dispatch_stub_749(void){} +void gl_dispatch_stub_769(void){} +void gl_dispatch_stub_770(void){} +void gl_dispatch_stub_771(void){} +void gl_dispatch_stub_772(void){} +void gl_dispatch_stub_773(void){} diff --git a/src/gallium/state_trackers/wgl/shared/stw_winsys.h b/src/gallium/state_trackers/wgl/shared/stw_winsys.h new file mode 100644 index 00000000000..a85a9a22577 --- /dev/null +++ b/src/gallium/state_trackers/wgl/shared/stw_winsys.h @@ -0,0 +1,59 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_WINSYS_H +#define STW_WINSYS_H + +#include <windows.h> /* for HDC */ + +#include "pipe/p_compiler.h" + +struct pipe_screen; +struct pipe_context; +struct pipe_surface; + +struct stw_winsys +{ + struct pipe_screen * + (*create_screen)( void ); + + struct pipe_context * + (*create_context)( struct pipe_screen *screen ); + + void + (*flush_frontbuffer)( struct pipe_screen *screen, + struct pipe_surface *surf, + HDC hDC ); +}; + +boolean +st_init(const struct stw_winsys *stw_winsys); + +void +st_cleanup(void); + +#endif /* STW_WINSYS_H */ diff --git a/src/gallium/state_trackers/wgl/stw.c b/src/gallium/state_trackers/wgl/stw.c new file mode 100644 index 00000000000..8bccdad2211 --- /dev/null +++ b/src/gallium/state_trackers/wgl/stw.c @@ -0,0 +1,57 @@ +/************************************************************************** + * + * Copyright 2009, VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include "stw.h" +#include "shared/stw_winsys.h" + +boolean +st_init(const struct stw_winsys *stw_winsys) +{ + if (!stw_shared_init( stw_winsys )) + goto fail; + + if (!stw_icd_init()) + goto fail; + + if (!stw_wgl_init()) + goto fail; + + return TRUE; + +fail: + st_cleanup(); + return FALSE; +} + + +void +st_cleanup(void) +{ + stw_icd_cleanup(); + stw_shared_cleanup(); + stw_wgl_cleanup(); +} diff --git a/src/gallium/state_trackers/wgl/stw.h b/src/gallium/state_trackers/wgl/stw.h new file mode 100644 index 00000000000..450af4ccb6f --- /dev/null +++ b/src/gallium/state_trackers/wgl/stw.h @@ -0,0 +1,53 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_H +#define STW_H + +#include "pipe/p_compiler.h" + +struct stw_winsys; + +/* Public interface: + */ +boolean stw_init( const struct stw_winsys *stw_winsys ); +void stw_cleanup( void ); + + + +/* Internal functions + */ +boolean stw_shared_init( const struct stw_winsys *stw_winsys ); +boolean stw_icd_init( void ); +boolean stw_wgl_init( void ); + +void stw_shared_cleanup( void ); +void stw_icd_cleanup( void ); +void stw_wgl_cleanup( void ); + + +#endif /* STW_H */ diff --git a/src/gallium/state_trackers/wgl/wgl/stw_wgl.c b/src/gallium/state_trackers/wgl/wgl/stw_wgl.c new file mode 100644 index 00000000000..f50b79b4e11 --- /dev/null +++ b/src/gallium/state_trackers/wgl/wgl/stw_wgl.c @@ -0,0 +1,353 @@ +/************************************************************************** + * + * Copyright 2008 Tungsten Graphics, Inc., Cedar Park, Texas. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL TUNGSTEN GRAPHICS AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#include <windows.h> + +#include "pipe/p_debug.h" +#include "shared/stw_public.h" +#include "stw_wgl.h" +#include "stw.h" + +boolean stw_wgl_init( void ) +{ + debug_printf("%s\n", __FUNCTION__); + return TRUE; +} + +void stw_wgl_cleanup( void ) +{ +} + +static INLINE struct stw_context *stw_context( HGLRC hglrc ) +{ + return (struct stw_context *)hglrc; +} + + +WINGDIAPI BOOL APIENTRY +wglCopyContext( + HGLRC hglrcSrc, + HGLRC hglrcDst, + UINT mask ) +{ + return stw_copy_context( stw_context(hglrcSrc), + stw_context(hglrcDst), + mask ); +} + +WINGDIAPI HGLRC APIENTRY +wglCreateContext( + HDC hdc ) +{ + return (HGLRC) stw_create_context( hdc, 0 ); +} + +WINGDIAPI HGLRC APIENTRY +wglCreateLayerContext( + HDC hdc, + int iLayerPlane ) +{ + return (HGLRC) stw_create_context( hdc, iLayerPlane ); +} + +WINGDIAPI BOOL APIENTRY +wglDeleteContext( + HGLRC hglrc ) +{ + return stw_delete_context( stw_context(hglrc) ); +} + + +WINGDIAPI HGLRC APIENTRY +wglGetCurrentContext( VOID ) +{ + return (HGLRC) stw_get_current_context(); +} + +WINGDIAPI HDC APIENTRY +wglGetCurrentDC( VOID ) +{ + return stw_get_current_dc(); +} + +WINGDIAPI BOOL APIENTRY +wglMakeCurrent( + HDC hdc, + HGLRC hglrc ) +{ + return stw_make_current( hdc, stw_context(hglrc) ); +} + + +WINGDIAPI BOOL APIENTRY +wglSwapBuffers( + HDC hdc ) +{ + return stw_swap_buffers( hdc ); +} + + +WINGDIAPI BOOL APIENTRY +wglSwapLayerBuffers( + HDC hdc, + UINT fuPlanes ) +{ + (void) hdc; + (void) fuPlanes; + + return FALSE; +} + +WINGDIAPI PROC APIENTRY +wglGetProcAddress( + LPCSTR lpszProc ) +{ + return stw_get_proc_address( lpszProc ); +} + + +WINGDIAPI int APIENTRY +wglChoosePixelFormat( + HDC hdc, + CONST PIXELFORMATDESCRIPTOR *ppfd ) +{ + if (ppfd->nSize != sizeof( PIXELFORMATDESCRIPTOR ) || ppfd->nVersion != 1) + return 0; + if (ppfd->iPixelType != PFD_TYPE_RGBA) + return 0; + if (!(ppfd->dwFlags & PFD_DRAW_TO_WINDOW)) + return 0; + if (!(ppfd->dwFlags & PFD_SUPPORT_OPENGL)) + return 0; + if (ppfd->dwFlags & PFD_DRAW_TO_BITMAP) + return 0; + if (ppfd->dwFlags & PFD_SUPPORT_GDI) + return 0; + if (!(ppfd->dwFlags & PFD_STEREO_DONTCARE) && (ppfd->dwFlags & PFD_STEREO)) + return 0; + + return stw_pixelformat_choose( hdc, ppfd ); +} + +WINGDIAPI int APIENTRY +wglDescribePixelFormat( + HDC hdc, + int iPixelFormat, + UINT nBytes, + LPPIXELFORMATDESCRIPTOR ppfd ) +{ + return stw_pixelformat_describe( hdc, iPixelFormat, nBytes, ppfd ); +} + +WINGDIAPI int APIENTRY +wglGetPixelFormat( + HDC hdc ) +{ + return stw_pixelformat_get( hdc ); +} + +WINGDIAPI BOOL APIENTRY +wglSetPixelFormat( + HDC hdc, + int iPixelFormat, + const PIXELFORMATDESCRIPTOR *ppfd ) +{ + if (ppfd->nSize != sizeof( PIXELFORMATDESCRIPTOR )) + return FALSE; + + return stw_pixelformat_set( hdc, iPixelFormat ); +} + + +WINGDIAPI BOOL APIENTRY +wglUseFontBitmapsA( + HDC hdc, + DWORD first, + DWORD count, + DWORD listBase ) +{ + (void) hdc; + (void) first; + (void) count; + (void) listBase; + + assert( 0 ); + + return FALSE; +} + +WINGDIAPI BOOL APIENTRY +wglShareLists( + HGLRC hglrc1, + HGLRC hglrc2 ) +{ + (void) hglrc1; + (void) hglrc2; + + assert( 0 ); + + return FALSE; +} + +WINGDIAPI BOOL APIENTRY +wglUseFontBitmapsW( + HDC hdc, + DWORD first, + DWORD count, + DWORD listBase ) +{ + (void) hdc; + (void) first; + (void) count; + (void) listBase; + + assert( 0 ); + + return FALSE; +} + +WINGDIAPI BOOL APIENTRY +wglUseFontOutlinesA( + HDC hdc, + DWORD first, + DWORD count, + DWORD listBase, + FLOAT deviation, + FLOAT extrusion, + int format, + LPGLYPHMETRICSFLOAT lpgmf ) +{ + (void) hdc; + (void) first; + (void) count; + (void) listBase; + (void) deviation; + (void) extrusion; + (void) format; + (void) lpgmf; + + assert( 0 ); + + return FALSE; +} + +WINGDIAPI BOOL APIENTRY +wglUseFontOutlinesW( + HDC hdc, + DWORD first, + DWORD count, + DWORD listBase, + FLOAT deviation, + FLOAT extrusion, + int format, + LPGLYPHMETRICSFLOAT lpgmf ) +{ + (void) hdc; + (void) first; + (void) count; + (void) listBase; + (void) deviation; + (void) extrusion; + (void) format; + (void) lpgmf; + + assert( 0 ); + + return FALSE; +} + +WINGDIAPI BOOL APIENTRY +wglDescribeLayerPlane( + HDC hdc, + int iPixelFormat, + int iLayerPlane, + UINT nBytes, + LPLAYERPLANEDESCRIPTOR plpd ) +{ + (void) hdc; + (void) iPixelFormat; + (void) iLayerPlane; + (void) nBytes; + (void) plpd; + + assert( 0 ); + + return FALSE; +} + +WINGDIAPI int APIENTRY +wglSetLayerPaletteEntries( + HDC hdc, + int iLayerPlane, + int iStart, + int cEntries, + CONST COLORREF *pcr ) +{ + (void) hdc; + (void) iLayerPlane; + (void) iStart; + (void) cEntries; + (void) pcr; + + assert( 0 ); + + return 0; +} + +WINGDIAPI int APIENTRY +wglGetLayerPaletteEntries( + HDC hdc, + int iLayerPlane, + int iStart, + int cEntries, + COLORREF *pcr ) +{ + (void) hdc; + (void) iLayerPlane; + (void) iStart; + (void) cEntries; + (void) pcr; + + assert( 0 ); + + return 0; +} + +WINGDIAPI BOOL APIENTRY +wglRealizeLayerPalette( + HDC hdc, + int iLayerPlane, + BOOL bRealize ) +{ + (void) hdc; + (void) iLayerPlane; + (void) bRealize; + + assert( 0 ); + + return FALSE; +} diff --git a/src/gallium/state_trackers/wgl/wgl/stw_wgl.h b/src/gallium/state_trackers/wgl/wgl/stw_wgl.h new file mode 100644 index 00000000000..b86cc240f28 --- /dev/null +++ b/src/gallium/state_trackers/wgl/wgl/stw_wgl.h @@ -0,0 +1,63 @@ +/************************************************************************** + * + * Copyright 2009 VMware, Inc. + * All Rights Reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, sub license, and/or sell copies of the Software, and to + * permit persons to whom the Software is furnished to do so, subject to + * the following conditions: + * + * The above copyright notice and this permission notice (including the + * next paragraph) shall be included in all copies or substantial portions + * of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT. + * IN NO EVENT SHALL VMWARE AND/OR ITS SUPPLIERS BE LIABLE FOR + * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, + * TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE + * SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. + * + **************************************************************************/ + +#ifndef STW_WGL_H_ +#define STW_WGL_H_ + + +#include <windows.h> + +#include "GL/gl.h" + + +/* + * Undeclared APIs exported by opengl32.dll + */ + +WINGDIAPI BOOL WINAPI +wglSwapBuffers(HDC hdc); + +WINGDIAPI int WINAPI +wglChoosePixelFormat(HDC hdc, + CONST PIXELFORMATDESCRIPTOR *ppfd); + +WINGDIAPI int WINAPI +wglDescribePixelFormat(HDC hdc, + int iPixelFormat, + UINT nBytes, + LPPIXELFORMATDESCRIPTOR ppfd); + +WINGDIAPI int WINAPI +wglGetPixelFormat(HDC hdc); + +WINGDIAPI BOOL WINAPI +wglSetPixelFormat(HDC hdc, + int iPixelFormat, + CONST PIXELFORMATDESCRIPTOR *ppfd); + + +#endif /* STW_WGL_H_ */ |