From 3287cff0b20b8754211c1427f7b92068860134fb Mon Sep 17 00:00:00 2001 From: "Sergey Semyonov (Serge)" Date: Thu, 15 Jan 2015 05:49:40 +0000 Subject: [PATCH] sdk: new pixlib. Now with OpenGL taste. git-svn-id: svn://kolibrios.org@5371 a494cfbc-eb01-0410-851d-a64ba20cac60 --- contrib/sdk/sources/pixlib-3/Makefile | 55 ++ contrib/sdk/sources/pixlib-3/egl.c | 116 ++++ contrib/sdk/sources/pixlib-3/pixdriver.h | 18 + contrib/sdk/sources/pixlib-3/pixlib.ver | 17 + contrib/sdk/sources/pixlib-3/pixlib3.c | 264 ++++++++ contrib/sdk/sources/pixlib-3/pixlib3.h | 33 + contrib/sdk/sources/pixlib-3/pxgl.c | 735 +++++++++++++++++++++++ contrib/sdk/sources/pixlib-3/pxgl.h | 67 +++ 8 files changed, 1305 insertions(+) create mode 100644 contrib/sdk/sources/pixlib-3/Makefile create mode 100644 contrib/sdk/sources/pixlib-3/egl.c create mode 100644 contrib/sdk/sources/pixlib-3/pixdriver.h create mode 100644 contrib/sdk/sources/pixlib-3/pixlib.ver create mode 100644 contrib/sdk/sources/pixlib-3/pixlib3.c create mode 100644 contrib/sdk/sources/pixlib-3/pixlib3.h create mode 100644 contrib/sdk/sources/pixlib-3/pxgl.c create mode 100644 contrib/sdk/sources/pixlib-3/pxgl.h diff --git a/contrib/sdk/sources/pixlib-3/Makefile b/contrib/sdk/sources/pixlib-3/Makefile new file mode 100644 index 0000000000..490fd7bcb8 --- /dev/null +++ b/contrib/sdk/sources/pixlib-3/Makefile @@ -0,0 +1,55 @@ +LIBRARY= pixlib3 + +CC = kos32-gcc +AR = kos32-ar +LD = kos32-ld +STRIP = kos32-strip + +ARFLAGS = crs +CFLAGS = -U_Win32 -U_WIN32 -U__MINGW32__ -c -O2 -fno-ident -fomit-frame-pointer +LDFLAGS:= -shared -s -nostdlib -Map px.map -T ../newlib/dll.lds --entry _DllStartup --image-base=0 +LDFLAGS+= --file-alignment 256 + +INCLUDES= -I. -I../newlib/libc/include + +PXGL_INCLUDES= $(INCLUDES) -I../libdrm/intel -I../libdrm/include +PXGL_INCLUDES+= -I ../Mesa/include -I../Mesa/src/gbm/main + +LIBPATH:= -L../../lib -L/home/autobuild/tools/win32/mingw32/lib + +LIBS:= -ldll -legl.dll -lGL.dll -lc.dll -lgcc +#LIBS+= -ldrm.dll + +DEFINES:= -DNDEBUG +PXGL_DEFINES:= $(DEFINES) -D__unix__ -DMESA_EGL_NO_X11_HEADERS + +SRC_PIXLIB = pixlib3.c +SRC_PXGL = egl.c pxgl.c + +OBJ_PIXLIB = $(patsubst %.c, %.o, $(SRC_PIXLIB)) +OBJ_PXGL = $(patsubst %.c, %.o, $(SRC_PXGL)) + +# targets + +all: lib$(LIBRARY).a pixlib-gl.dll + +lib$(LIBRARY).a: $(OBJ_PIXLIB) Makefile + $(AR) $(ARFLAGS) lib$(LIBRARY).a $(OBJ_PIXLIB) + mv -f lib$(LIBRARY).a ../../lib + +pixlib-gl.dll: $(OBJ_PXGL) Makefile + $(LD) $(LDFLAGS) $(PXFLAGS) $(LIBPATH) -o $@ $(OBJ_PXGL) $(LIBS) + mv -f $@ ../../bin + +pixlib3.o : pixlib3.c Makefile + $(CC) $(CFLAGS) $(DEFINES) $(INCLUDES) -o $@ $< + +%.o : %.c Makefile + $(CC) $(CFLAGS) $(PXGL_DEFINES) $(PXGL_INCLUDES) -o $@ $< + +clean: + -rm -f *.o + + + + diff --git a/contrib/sdk/sources/pixlib-3/egl.c b/contrib/sdk/sources/pixlib-3/egl.c new file mode 100644 index 0000000000..14ca37c3a0 --- /dev/null +++ b/contrib/sdk/sources/pixlib-3/egl.c @@ -0,0 +1,116 @@ + +#include +#include +#include +#include +#include + +#define EGL_EGLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES + +#include "EGL/egl.h" +#include "EGL/eglext.h" +#include "GL/gl.h" +#include "gbm.h" +#include "pxgl.h" + +static struct gbm_device *gbm; + +static EGLConfig choose_config(EGLDisplay *dpy) +{ + EGLConfig config = NULL; + EGLint config_attribs[32]; + EGLint num_configs, i; + + i = 0; + config_attribs[i++] = EGL_RED_SIZE; + config_attribs[i++] = 1; + config_attribs[i++] = EGL_GREEN_SIZE; + config_attribs[i++] = 1; + config_attribs[i++] = EGL_BLUE_SIZE; + config_attribs[i++] = 1; + config_attribs[i++] = EGL_DEPTH_SIZE; + config_attribs[i++] = 1; + + config_attribs[i++] = EGL_SURFACE_TYPE; + config_attribs[i++] = EGL_WINDOW_BIT; + + config_attribs[i++] = EGL_RENDERABLE_TYPE; + config_attribs[i++] = EGL_OPENGL_BIT; + config_attribs[i] = EGL_NONE; + + eglChooseConfig(dpy, config_attribs, &config, 1, &num_configs); + + return config; +}; + +int egl_initialize(EGLDisplay *dpy, EGLConfig *config, EGLContext *context) +{ + EGLint major, minor; + int fd; + + fd = get_service("DISPLAY"); + if(fd == 0) + return -1; + + gbm = gbm_create_device(fd); + if( gbm == NULL) + { + DBG("failed to initialize GBM device\n"); + goto err_0; + }; + + *dpy = eglGetDisplay(gbm); + + if (!eglInitialize(*dpy, &major, &minor)) + { + DBG("failed to initialize EGL display\n"); + goto err_1; + }; + + DBG("EGL_VERSION = %s\n", eglQueryString(*dpy, EGL_VERSION)); + DBG("EGL_VENDOR = %s\n", eglQueryString(*dpy, EGL_VENDOR)); + DBG("EGL_EXTENSIONS = %s\n", eglQueryString(*dpy, EGL_EXTENSIONS)); + DBG("EGL_CLIENT_APIS = %s\n", eglQueryString(*dpy, EGL_CLIENT_APIS)); + + *config = choose_config(*dpy); + if( *config == NULL) + { + DBG("failed to choose a config\n"); + goto err_2; + }; + + eglBindAPI(EGL_OPENGL_API); + *context = eglCreateContext(*dpy, *config, EGL_NO_CONTEXT, NULL); + if (context == NULL) + { + DBG("failed to create context\n"); + goto err_2; + }; + + if (!eglMakeCurrent(*dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, *context)) + { + DBG("failed to make context current"); + goto err_3; + }; + + return 0; + +err_3: + eglDestroyContext(*dpy, *context); +err_2: + eglTerminate(*dpy); +err_1: + gbm_device_destroy(gbm); +err_0: + return -1; +}; + +void egl_destroy(EGLDisplay dpy, EGLContext context) +{ + eglMakeCurrent(dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT); + eglDestroyContext(dpy, context); + eglTerminate(dpy); + gbm_device_destroy(gbm); +}; + diff --git a/contrib/sdk/sources/pixlib-3/pixdriver.h b/contrib/sdk/sources/pixlib-3/pixdriver.h new file mode 100644 index 0000000000..b6381dba7e --- /dev/null +++ b/contrib/sdk/sources/pixlib-3/pixdriver.h @@ -0,0 +1,18 @@ +#ifndef __PIXDRIVER_H__ +#define __PIXDRIVER_H__ + +struct pix_driver +{ + uint32_t driver_caps; + bitmap_t *(*create_bitmap)(uint32_t width, uint32_t height); + int (*destroy_bitmap)(bitmap_t *bitmap); + void *(*lock_bitmap)(bitmap_t *bitmap, uint32_t *pitch); + int (*resize_bitmap)(bitmap_t *bitmap, uint32_t width, uint32_t height); + int (*blit_bitmap)(bitmap_t * bitmap, int dst_x, int dst_y, + uint32_t w, uint32_t h, int src_x, int src_y); + int (*create_client)(int x, int y, uint32_t width, uint32_t height); + int (*resize_client)(int x, int y, uint32_t width, uint32_t height); + void (*fini)(void); +}; + +#endif diff --git a/contrib/sdk/sources/pixlib-3/pixlib.ver b/contrib/sdk/sources/pixlib-3/pixlib.ver new file mode 100644 index 0000000000..b5f0347a65 --- /dev/null +++ b/contrib/sdk/sources/pixlib-3/pixlib.ver @@ -0,0 +1,17 @@ +LIBDRM { + global: DllStartup; + init_pixlib; + done_pixlib; + create_bitmap; + resize_bitmap; + destroy_bitmap; + lock_bitmap; + blit_bitmap; + + local: __chkstk; + __chkstk_ms; + _alloca; + __uxa_lock; + _nm__tls_alloc; + *; +}; diff --git a/contrib/sdk/sources/pixlib-3/pixlib3.c b/contrib/sdk/sources/pixlib-3/pixlib3.c new file mode 100644 index 0000000000..9e913da5d9 --- /dev/null +++ b/contrib/sdk/sources/pixlib-3/pixlib3.c @@ -0,0 +1,264 @@ +#include +#include +#include +#include + +#include "pixlib3.h" +#include "pixdriver.h" + +#define DISPLAY_VERSION 0x0200 /* 2.00 */ + +#define SRV_GETVERSION 0 +#define SRV_GET_CAPS 3 + + +#define BUFFER_SIZE(n) ((n)*sizeof(uint32_t)) +#define __ALIGN_MASK(x,mask) (((x)+(mask))&~(mask)) +#define ALIGN(x,a) __ALIGN_MASK(x,(typeof(x))(a)-1) + +struct bitmap +{ + uint32_t width; + uint32_t height; + uint32_t pitch; + void *buffer; + uint32_t size; +}; + +static uint32_t fd; +static struct pix_driver *driver; + + +static bitmap_t *sw_create_bitmap(uint32_t width, uint32_t height) +{ + bitmap_t *bitmap; + + bitmap = malloc(sizeof(bitmap_t)); + if(bitmap == NULL) + goto err_0; + + bitmap->width = width; + bitmap->height = height; + + bitmap->pitch = ALIGN(width * 4, 16); + bitmap->size = ALIGN(bitmap->pitch * height, 4096); + + bitmap->buffer = user_alloc(bitmap->size); + if (bitmap->buffer == NULL) + goto err_1; + + printf("create bitmap: %p %dx%d buffer: %p\n", + bitmap, bitmap->width, bitmap->height, bitmap->buffer); + + return bitmap; + +err_1: + free(bitmap); +err_0: + return NULL; +}; + +static int sw_destroy_bitmap(bitmap_t * bitmap) +{ + user_free(bitmap->buffer); + free(bitmap); + return 0; +}; + +static void *sw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch) +{ + *pitch = bitmap->pitch; + + return bitmap->buffer; +}; + +static int sw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height) +{ + uint32_t size; + uint32_t pitch; + + pitch = ALIGN(width * 4, 16); + size = ALIGN(pitch * height, 4096); + + if (size > bitmap->size) + { + bitmap->buffer = user_realloc(bitmap->buffer, size); /* grow buffer */ + if (bitmap->buffer == NULL) + return -1; + + bitmap->size = size; + } + else if (size < bitmap->size) + user_unmap(bitmap->buffer, size, bitmap->size - size); /* unmap unused pages */ + + bitmap->width = width; + bitmap->height = height; + bitmap->pitch = pitch; + + return 0; +}; + +static int sw_blit(bitmap_t * bitmap, int dst_x, int dst_y, + uint32_t w, uint32_t h, int src_x, int src_y) +{ + struct blit_call bc; + int ret; + + bc.dstx = dst_x; + bc.dsty = dst_y; + bc.w = w; + bc.h = h; + bc.srcx = src_x; + bc.srcy = src_y; + bc.srcw = bitmap->width; + bc.srch = bitmap->height; + bc.stride = bitmap->pitch; + bc.bitmap = bitmap->buffer; + + __asm__ __volatile__( + "int $0x40":"=a"(ret):"a"(73), "b"(0x00), + "c"(&bc):"memory"); + + return ret; +}; + +static int sw_create_client(int x, int y, uint32_t width, uint32_t height) +{ + return 0; +}; + +static int sw_resize_client(int x, int y, uint32_t width, uint32_t height) +{ + return 0; +}; + +bitmap_t *pxCreateBitmap(uint32_t width, uint32_t height) +{ + return driver->create_bitmap(width, height); +}; + +int pxDestroyBitmap(bitmap_t *bitmap) +{ + return driver->destroy_bitmap(bitmap); +}; + +void *pxLockBitmap(bitmap_t *bitmap, uint32_t *pitch) +{ + return driver->lock_bitmap(bitmap, pitch); +}; + +int pxResizeBitmap(bitmap_t *bitmap, uint32_t width, uint32_t height) +{ + return driver->resize_bitmap(bitmap, width, height); +}; + +int pxBlitBitmap(bitmap_t *bitmap, int dst_x, int dst_y, + uint32_t w, uint32_t h, int src_x, int src_y) +{ + return driver->blit_bitmap(bitmap, dst_x, dst_y, + w, h, src_x, src_y); +}; + +int pxCreateClient(int x, int y, uint32_t width, uint32_t height) +{ + return driver->create_client(x, y, width, height); +} + +int pxResizeClient(int x, int y, uint32_t width, uint32_t height) +{ + printf("resize client\n"); + return driver->resize_client(x, y, width, height); +} + +static struct pix_driver sw_driver = +{ + 0, + sw_create_bitmap, + sw_destroy_bitmap, + sw_lock_bitmap, + sw_resize_bitmap, + sw_blit, + sw_create_client, + sw_resize_client, + NULL +}; + + +uint32_t pxInit(int hw) +{ + void *lib; + struct pix_driver *(*drventry)(uint32_t service); + + uint32_t api_version; + ioctl_t io; + + driver = &sw_driver; + + if(hw == 0) + return 0; + + if (fd != 0) + return driver->driver_caps; + + fd = get_service("DISPLAY"); + if (fd == 0) + goto fail; + + io.handle = fd; + io.io_code = SRV_GETVERSION; + io.input = NULL; + io.inp_size = 0; + io.output = &api_version; + io.out_size = BUFFER_SIZE(1); + + if (call_service(&io) != 0) + goto fail; + + if ((DISPLAY_VERSION > (api_version & 0xFFFF)) || + (DISPLAY_VERSION < (api_version >> 16))) + goto fail; + + lib = load_library("pixlib-gl.dll"); + if(lib == 0) + goto fail; + + drventry = get_proc_address(lib, "DrvInit"); + + if( drventry == NULL) + goto fail; + + driver = drventry(fd); + if(driver == NULL) + { + driver = &sw_driver; + goto fail; + }; + + if (driver->driver_caps) + printf("2D caps %s%s%s\n", + (driver->driver_caps & HW_BIT_BLIT) != 0 ? "HW_BIT_BLIT " : "", + (driver->driver_caps & HW_TEX_BLIT) != 0 ? "HW_TEX_BLIT " : "", + (driver->driver_caps & HW_VID_BLIT) != 0 ? "HW_VID_BLIT " : ""); + + return driver->driver_caps; + +fail: + printf("Warning! Hardware initialization failed.\n" + "fallback to software rendering.\n"); + fd = 0; + return 0; +}; + +void pxFini() +{ + if (driver->fini) + driver->fini(); +}; + + + + + + + + diff --git a/contrib/sdk/sources/pixlib-3/pixlib3.h b/contrib/sdk/sources/pixlib-3/pixlib3.h new file mode 100644 index 0000000000..afab7aa6f6 --- /dev/null +++ b/contrib/sdk/sources/pixlib-3/pixlib3.h @@ -0,0 +1,33 @@ +#ifndef __PIXLIB3_H__ +#define __PIXLIB3_H__ + +#include + +#define HW_BIT_BLIT (1<<0) /* BGRX blitter */ +#define HW_TEX_BLIT (1<<1) /* stretch blit */ +#define HW_VID_BLIT (1<<2) /* planar and packed video */ + + +struct bitmap; +typedef struct bitmap bitmap_t; + +uint32_t pxInit(int hw); +void pxFini(); + +bitmap_t *pxCreateBitmap(uint32_t width, uint32_t height); + +int pxDestroyBitmap(bitmap_t *bitmap); + +void *pxLockBitmap(bitmap_t *bitmap, uint32_t *pitch); + +int pxResizeBitmap(bitmap_t *bitmap, uint32_t width, uint32_t height); + +int pxBlitBitmap(bitmap_t *bitmap, int dst_x, int dst_y, + uint32_t w, uint32_t h, int src_x, int src_y); + +int pxCreateClient(int x, int y, uint32_t width, uint32_t height); + +int pxResizeClient(int x, int y, uint32_t width, uint32_t height); + +#endif + diff --git a/contrib/sdk/sources/pixlib-3/pxgl.c b/contrib/sdk/sources/pixlib-3/pxgl.c new file mode 100644 index 0000000000..3e6bdeb414 --- /dev/null +++ b/contrib/sdk/sources/pixlib-3/pxgl.c @@ -0,0 +1,735 @@ +#include +#include +#include +#include +#include +#include "pixlib3.h" +#include "pixdriver.h" +#include "pxgl.h" + +#define WIN_STATE_MINIMIZED 0x02 +#define WIN_STATE_ROLLED 0x04 + +static int drm_ioctl(int fd, unsigned long request, void *arg) +{ + ioctl_t io; + + io.handle = fd; + io.io_code = request; + io.input = arg; + io.inp_size = 64; + io.output = NULL; + io.out_size = 0; + + return call_service(&io); +} + +static EGLImageKHR px_create_image(struct render *px,void *name,GLuint tex, EGLint *attribs) +{ + EGLImageKHR image; + + image = eglCreateImageKHR(px->dpy, px->context, + EGL_DRM_BUFFER_MESA, name, attribs); + if(image == NULL) + goto err_0; + + glBindTexture(GL_TEXTURE_2D, tex); + if(glGetError() != GL_NO_ERROR) + goto err_1; + + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, image); + if(glGetError() != GL_NO_ERROR) + goto err_1; + + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST); + glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST); + + return image; + +err_1: + eglDestroyImageKHR(px->dpy, image); +err_0: + return NULL; +}; + +static int update_fb(struct render *px, int name, int pitch) +{ + GLenum status; + EGLImageKHR screen; + + EGLint attribs[] = { + EGL_WIDTH, px->scr_width, + EGL_HEIGHT, px->scr_height, + EGL_DRM_BUFFER_STRIDE_MESA, pitch/4, + EGL_DRM_BUFFER_FORMAT_MESA, + EGL_DRM_BUFFER_FORMAT_ARGB32_MESA, + EGL_DRM_BUFFER_USE_MESA, + EGL_DRM_BUFFER_USE_SHARE_MESA | + EGL_DRM_BUFFER_USE_SCANOUT_MESA, + EGL_NONE + }; + char *errmsg; + + px->screen = px_create_image(px,(void*)name, px->texture[TEX_SCREEN], attribs); + errmsg = "failed to create new screen image\n"; + if(px->screen == EGL_NO_IMAGE_KHR) + goto err_0; + + px->screen = screen; + + glFramebufferTexture2D(GL_FRAMEBUFFER,GL_COLOR_ATTACHMENT0, + GL_TEXTURE_2D, px->texture[TEX_SCREEN],0); + + status = glCheckFramebufferStatus(GL_FRAMEBUFFER); + if (status != GL_FRAMEBUFFER_COMPLETE) + { + const char *str; + switch (status) + { + case GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT: + str = "incomplete attachment"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT: + str = "incomplete/missing attachment"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_DRAW_BUFFER: + str = "incomplete draw buffer"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_READ_BUFFER: + str = "incomplete read buffer"; + break; + case GL_FRAMEBUFFER_UNSUPPORTED: + str = "unsupported"; + break; + case GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE: + str = "incomplete multiple"; + break; + default: + str = "unknown error"; + break; + } + DBG("destination framebuffer incomplete: %s [%#x]\n", str, status); + + return -1; + }; + + DBG("framebuffer changed successfull\n"); + + glViewport(0, 0, px->scr_width, px->scr_height); + + return 0; + +err_0: + DBG("%s %s\n", __FUNCTION__, errmsg); + + return -1; +}; + +static GLint create_shader(GLenum type, const char *source) +{ + GLint ok; + GLint shader; + + shader = glCreateShader(type); + if(shader == 0) + goto err; + + glShaderSource(shader, 1, (const GLchar **) &source, NULL); + glCompileShader(shader); + glGetShaderiv(shader, GL_COMPILE_STATUS, &ok); + if (!ok) { + GLchar *info; + GLint size; + + glGetShaderiv(shader, GL_INFO_LOG_LENGTH, &size); + info = malloc(size); + + glGetShaderInfoLog(shader, size, NULL, info); + DBG("Failed to compile %s: %s\n", + type == GL_FRAGMENT_SHADER ? "FS" : "VS",info); + DBG("Program source:\n%s", source); + DBG("GLSL compile failure\n"); + free(info); + glDeleteShader(shader); + shader = 0; + }; + + DBG("create shader %d\n", shader); +err: + return shader; +} + + +static void *px_create_obj(struct render *px, size_t size, + GLuint *handle, GLuint *name) +{ + struct drm_i915_gem_create create; + struct drm_i915_gem_mmap mmap_arg; + struct drm_gem_close close; + struct drm_gem_flink flink; + + create.size = size; + create.handle = 0; + + if(drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_CREATE, &create)) + goto err_0; + + *handle = create.handle; + flink.handle = create.handle; + if (drm_ioctl(px->fd, DRM_IOCTL_GEM_FLINK, &flink)) + goto err_1; + + *name = flink.name; + + mmap_arg.handle = *handle; + mmap_arg.offset = 0; + mmap_arg.size = size; + if (drm_ioctl(px->fd, DRM_IOCTL_I915_GEM_MMAP, &mmap_arg)) + { + DBG("%s: failed to mmap bitmap handle=%d, %d bytes, into CPU domain\n", + __FUNCTION__, *handle, size); + goto err_1; + }; + + return (void*)(uintptr_t)mmap_arg.addr_ptr; + +err_1: + close.handle = *handle; + drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); +err_0: + return NULL; +}; + + +static int px_create_bitmap(struct render *px, struct bitmap *bitmap, + size_t size, EGLint format) +{ + struct drm_gem_close close; + EGLint attribs[] = { + EGL_WIDTH, bitmap->width, + EGL_HEIGHT, bitmap->height, + EGL_DRM_BUFFER_STRIDE_MESA, 0, + EGL_DRM_BUFFER_FORMAT_MESA, + format, + EGL_DRM_BUFFER_USE_MESA, + EGL_DRM_BUFFER_USE_SHARE_MESA, + EGL_NONE + }; + + bitmap->buffer = px_create_obj(px, size, &bitmap->handle, &bitmap->name); + if(bitmap->buffer == NULL) + goto err_0; + + switch(format) + { + case EGL_DRM_BUFFER_FORMAT_ARGB32_MESA: + attribs[5] = bitmap->pitch/4; + break; + case EGL_DRM_BUFFER_FORMAT_R8_MESA: + attribs[5] = bitmap->pitch; + break; + default: + DBG("%s invalid format %x\n", + __FUNCTION__, format); + goto err_1; + } + + bitmap->image = px_create_image(px,(void*)bitmap->name, + bitmap->tex, attribs); + if(bitmap->image == NULL) + goto err_1; + + DBG("create bitmap:%p %dx%d pitch:%d\n" + "KHRimage:%p gl_tex:%d handle:%d name:%d\n" + "mapped at %x\n", + bitmap, bitmap->width, bitmap->height, bitmap->pitch, + bitmap->image, bitmap->tex, bitmap->handle, bitmap->name, + bitmap->buffer); + + return 0; + +err_1: + user_free(bitmap->buffer); + close.handle = bitmap->handle; + drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); +err_0: + return -1; +} + + +static int create_mask(struct render *px) +{ + struct drm_i915_mask_update update; + int pitch; + + pitch = (px->width+15) & ~15; + + px->mask.width = px->width; + px->mask.height = px->height; + px->mask.pitch = pitch; + px->mask.tex = px->texture[TEX_MASK]; + px->mask_size = pitch * px->height; + + if(px_create_bitmap(px, &px->mask, px->mask_size, + EGL_DRM_BUFFER_FORMAT_R8_MESA) == 0) + { + update.handle = px->mask.handle; + update.dx = px->dx; + update.dy = px->dy; + update.width = px->width; + update.height = px->height; + update.bo_pitch = (px->width+15) & ~15; + update.bo_map = (int)px->mask.buffer; + update.forced = 1; + drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update); + return 0; + }; + return -1; +}; + + +static int update_mask(struct render *px) +{ + struct drm_gem_close close; + EGLint attribs[] = { + EGL_WIDTH, 0, + EGL_HEIGHT, 0, + EGL_DRM_BUFFER_STRIDE_MESA, 0, + EGL_DRM_BUFFER_FORMAT_MESA, + EGL_DRM_BUFFER_FORMAT_R8_MESA, + EGL_DRM_BUFFER_USE_MESA, + EGL_DRM_BUFFER_USE_SHARE_MESA, + EGL_NONE + }; + unsigned int size, pitch; + + eglDestroyImageKHR(px->dpy, px->mask.image); + + pitch = (px->width+15) & ~15; + size = pitch*px->height; + + if(size > px->mask_size) + { + user_free(px->mask.buffer); + close.handle = px->mask.handle; + drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); + + px->mask_size = size; + + px->mask.buffer = px_create_obj(px, px->mask_size, + &px->mask.handle, &px->mask.name); + if(px->mask.buffer == 0) + goto err_0; + }; + + attribs[1] = px->width; + attribs[3] = px->height; + attribs[5] = pitch; + + px->mask.image = px_create_image(px,(void*)px->mask.name, + px->mask.tex, attribs); + if(px->mask.image == NULL) + goto err_1; + + DBG("create mask w:%d h:%d pitch:%d\n" + "KHRimage:%p gl_tex:%d handle:%d name:%d\n" + "mapped at %x\n", + px->width, px->height, + pitch, px->mask.image, px->texture[TEX_MASK], + px->mask.handle, px->mask.name, px->mask.buffer); + + return 0; + +err_1: + user_free(px->mask.buffer); + close.handle = px->mask.handle; + drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); +err_0: + return -1; +}; + +static struct render* create_render(EGLDisplay dpy, EGLContext context, int dx, int dy, int w, int h) +{ + const char *vs_src = + "attribute vec4 v_position;\n" + "attribute vec4 v_texcoord0;\n" + "varying vec2 source_texture;\n" + "void main()\n" + "{\n" + " gl_Position = v_position;\n" + " source_texture = v_texcoord0.xy;\n" + "}\n"; + + const char *fs_i965 = + "varying vec2 source_texture;\n" + "uniform sampler2D sampler_src;\n" + "uniform sampler2D sampler_mask;\n" + "void main()\n" + "{\n" + " float ca = texture2D(sampler_mask, source_texture).r;\n" + " gl_FragColor = vec4(texture2D(sampler_src, source_texture).rgb, ca);\n" + "}\n"; + + struct drm_i915_fb_info fb; + struct render *px; + GLint vs_shader, fs_shader; + int ret; + + px = (struct render*)malloc(sizeof(struct render)); + if(px == NULL) + goto err_0; + + px->fd = get_service("DISPLAY"); + + __builtin_memset(&fb, 0, sizeof(fb)); + if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) + { DBG("failed to get framebuffer info\n"); + goto err_1; + }; + + px->dpy = dpy; + px->context = context; + px->dx = dx; + px->dy = dy; + px->width = w; + px->height = h; + px->scr_width = fb.width; + px->scr_height = fb.height; + + glGenTextures(2, px->texture); + if(glGetError() != GL_NO_ERROR) + goto err_1; + + glGenFramebuffers(1, &px->framebuffer); + if(glGetError() != GL_NO_ERROR) + goto err_2; + + glBindFramebuffer(GL_FRAMEBUFFER, px->framebuffer); + if(glGetError() != GL_NO_ERROR) + goto err_3; + + if(update_fb(px, fb.name, fb.pitch)) + goto err_4; + + glMatrixMode(GL_PROJECTION); + glLoadIdentity(); + glMatrixMode(GL_MODELVIEW); + glLoadIdentity(); + + if(create_mask(px)) + goto err_4; + + px->blit_prog = glCreateProgram(); + if(px->blit_prog == 0) + goto err_4; + + vs_shader = create_shader(GL_VERTEX_SHADER, vs_src); + if(vs_shader == 0) + goto err_4; + + fs_shader = create_shader(GL_FRAGMENT_SHADER, fs_i965); + if(fs_shader == 0) + goto err_4; + + glAttachShader(px->blit_prog, vs_shader); + glAttachShader(px->blit_prog, fs_shader); + glBindAttribLocation(px->blit_prog, 0, "v_position"); + glBindAttribLocation(px->blit_prog, 1, "v_texcoord0"); + + glLinkProgram(px->blit_prog); + glGetProgramiv(px->blit_prog, GL_LINK_STATUS, &ret); + if (!ret) + { + GLchar *info; + GLint size; + + glGetProgramiv(px->blit_prog, GL_INFO_LOG_LENGTH, &size); + info = malloc(size); + + glGetProgramInfoLog(px->blit_prog, size, NULL, info); + DBG("Failed to link: %s\n", info); + DBG("GLSL link failure\n"); + free(info); + goto err_4; + } + + px->sampler = glGetUniformLocation(px->blit_prog,"sampler_src"); + px->sm_mask = glGetUniformLocation(px->blit_prog,"sampler_mask"); + + glUseProgram(px->blit_prog); + glUniform1i(px->sampler, 0); + glUniform1i(px->sm_mask, 1); + + glEnableClientState(GL_VERTEX_ARRAY); + + glVertexAttribPointer(0, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->vertices); + glEnableVertexAttribArray(0); + + glVertexAttribPointer(1, 2, GL_FLOAT,GL_FALSE, 2 * sizeof(float),px->tc_src); + glEnableVertexAttribArray(1); + + glEnable(GL_BLEND); + glBlendFunc(GL_SRC_ALPHA,GL_ONE_MINUS_SRC_ALPHA); + + px->tc_src[0] = 0.0; + px->tc_src[1] = 0.0; + px->tc_src[1*2] = 1.0; + px->tc_src[1*2+1]= 0.0; + px->tc_src[2*2] = 1.0; + px->tc_src[2*2+1]= 1.0; + px->tc_src[3*2] = 0.0; + px->tc_src[3*2+1]= 1.0; + + DBG("create render framebuffer:%p %dx%d pitch:%d name %d\n", + px->screen,fb.width, fb.height, fb.pitch, fb.name); + + return px; + +err_4: + glBindFramebuffer(GL_FRAMEBUFFER, 0); +err_3: + glDeleteFramebuffers(1, &px->framebuffer); +err_2: + glDeleteTextures(2, px->texture); +err_1: + free(px); +err_0: + return NULL; +}; + +static struct render *px; + +static bitmap_t *hw_create_bitmap(uint32_t width, uint32_t height) +{ + struct bitmap *bitmap; + + bitmap = malloc(sizeof(struct bitmap)); + if(bitmap == NULL) + return NULL; + + glGenTextures(1, &bitmap->tex); + if(glGetError() != GL_NO_ERROR) + goto err_0; + + bitmap->width = width; + bitmap->height = height; + bitmap->pitch = (width*4 + 15) & ~15; + + if(px_create_bitmap(px, bitmap, bitmap->pitch * bitmap->height, + EGL_DRM_BUFFER_FORMAT_ARGB32_MESA) == 0) + { + return bitmap; + }; + + glDeleteTextures(1, &bitmap->tex); +err_0: + free(bitmap); + return NULL; +}; + +static int hw_destroy_bitmap(bitmap_t * bitmap) +{ + struct drm_gem_close close; + + glDeleteTextures(1, &bitmap->tex); + eglDestroyImageKHR(px->dpy, bitmap->image); + user_free(bitmap->buffer); + close.handle = bitmap->handle; + drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); + free(bitmap); +}; + +static void *hw_lock_bitmap(bitmap_t *bitmap, uint32_t *pitch) +{ + *pitch = bitmap->pitch; + + return bitmap->buffer; +}; + +static int hw_resize_bitmap(bitmap_t * bitmap, uint32_t width, uint32_t height) +{ + return 0; +} + +char proc_info[1024]; + +static int hw_blit(bitmap_t *bitmap, int dst_x, int dst_y, + uint32_t w, uint32_t h, int src_x, int src_y) +{ + struct drm_i915_mask_update update; + struct drm_i915_fb_info fb; + + uint32_t winx, winy, winw, winh; + uint8_t state; + float xscale, yscale; + int r, b; + float *vertices = px->vertices; + + get_proc_info(proc_info); + + state = *(uint8_t*)(proc_info+70); + if(state & (WIN_STATE_MINIMIZED|WIN_STATE_ROLLED)) + return; + + winx = *(uint32_t*)(proc_info+34); + winy = *(uint32_t*)(proc_info+38); + winw = *(uint32_t*)(proc_info+42)+1; + winh = *(uint32_t*)(proc_info+46)+1; + + __builtin_memset(&fb, 0, sizeof(fb)); + if( 0 != drm_ioctl(px->fd, SRV_FBINFO, &fb)) + { + DBG("failed to get framebuffer info\n"); + return; + }; + + if( fb.width != px->scr_width || + fb.height != px->scr_height ) + { + px->scr_width = fb.width; + px->scr_height = fb.height; + + eglDestroyImageKHR(px->dpy, px->screen); + + if(update_fb(px, fb.name, fb.pitch)) + return; + }; + + update.handle = px->mask.handle; + update.dx = px->dx; + update.dy = px->dy; + update.width = px->width; + update.height = px->height; + update.bo_pitch = (px->width+15) & ~15; + update.bo_map = (int)px->mask.buffer; + + if(drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update)) + { + return; + } + + xscale = 1.0/px->scr_width; + yscale = 1.0/px->scr_height; + + r = winx + px->dx + px->width; + b = winy + px->dy + px->height; + + float t0, t1, t2, t5; + +// render->tc_src[1*2] = 1.0; +// render->tc_src[2*2] = 1.0; +// render->tc_src[2*2+1]= 1.0; +// render->tc_src[3*2+1]= 1.0; + + vertices[0] = t0 = 2*(winx+px->dx)*xscale - 1.0; + vertices[1 * 2] = t2 = 2*r*xscale - 1.0; + + vertices[2 * 2] = t2; + vertices[3 * 2] = t0; + + vertices[1] = t1 = 2*(winy+px->dy)*yscale - 1.0; + vertices[2*2+1] = t5 = 2*b*yscale - 1.0; + vertices[1*2+1] = t1; + vertices[3*2+1] = t5; + + glActiveTexture(GL_TEXTURE0); + glBindTexture(GL_TEXTURE_2D, bitmap->tex); + + glActiveTexture(GL_TEXTURE1); + glBindTexture(GL_TEXTURE_2D, px->texture[TEX_MASK]); + + glDrawArrays(GL_TRIANGLE_FAN, 0, 4); + + glFlush(); + + return; +}; + +static int hw_create_client(int x, int y, uint32_t width, uint32_t height) +{ + px = create_render(eglGetCurrentDisplay(), eglGetCurrentContext(), x, y, width, height); + + return !px; +}; + +static int hw_resize_client(int x, int y, uint32_t width, uint32_t height) +{ + if( x != px->dx || + y != px->dy || + width != px->width || + height != px->height ) + { + struct drm_i915_mask_update update; + + px->dx = x; + px->dy = y; + px->width = width; + px->height = height; + update_mask(px); + + update.handle = px->mask.handle; + update.dx = px->dx; + update.dy = px->dy; + update.width = px->width; + update.height = px->height; + update.bo_pitch = (px->width+15) & ~15; + update.bo_map = (int)px->mask.buffer; + update.forced = 1; + + drm_ioctl(px->fd, SRV_MASK_UPDATE_EX, &update); + }; + + return 0; +}; + +static void hw_fini(void) +{ + struct drm_gem_close close; + + DBG("%s\n", __FUNCTION__); + + eglDestroyImageKHR(px->dpy, px->mask.image); + user_free(px->mask.buffer); + close.handle = px->mask.handle; + drm_ioctl(px->fd, DRM_IOCTL_GEM_CLOSE, &close); + + glBindFramebuffer(GL_FRAMEBUFFER, 0); + glDeleteFramebuffers(1, &px->framebuffer); + eglDestroyImageKHR(px->dpy, px->screen); + glDeleteTextures(2, px->texture); + egl_destroy(px->dpy, px->context); + free(px); +}; + +static struct pix_driver gl_driver = +{ + HW_TEX_BLIT, + hw_create_bitmap, + hw_destroy_bitmap, + hw_lock_bitmap, + hw_resize_bitmap, + hw_blit, + hw_create_client, + hw_resize_client, + hw_fini +}; + +struct pix_driver *DrvInit(uint32_t service) +{ + EGLDisplay dpy; + EGLConfig config; + EGLContext context; + int ret; + + ret = egl_initialize(&dpy, &config, &context); + if( ret ) + return NULL; + + return &gl_driver; + +err_0: + egl_destroy(dpy, context); + return NULL; +} + + diff --git a/contrib/sdk/sources/pixlib-3/pxgl.h b/contrib/sdk/sources/pixlib-3/pxgl.h new file mode 100644 index 0000000000..6c71616639 --- /dev/null +++ b/contrib/sdk/sources/pixlib-3/pxgl.h @@ -0,0 +1,67 @@ +#ifndef __GL_RENDER_H__ +#define __GL_RENDER_H__ + +#define EGL_EGLEXT_PROTOTYPES +#define GL_GLEXT_PROTOTYPES + +#include "EGL/egl.h" +#include "EGL/eglext.h" +#include "GL/gl.h" + +struct bitmap +{ + uint32_t width; + uint32_t height; + uint32_t pitch; + void *buffer; + GLuint tex; + GLuint handle; + GLuint name; + EGLImageKHR image; +}; + +enum +{ + TEX_SCREEN = 0, + TEX_MASK = 1 +}; + +struct render +{ + int fd; + EGLDisplay dpy; + EGLContext context; + EGLint dx; + EGLint dy; + EGLint width; + EGLint height; + EGLint scr_width; + EGLint scr_height; + GLuint texture[2]; + GLuint framebuffer; + EGLImageKHR screen; + struct bitmap mask; + + int mask_size; + + GLuint blit_prog; + GLint sampler, sm_mask; + float vertices[8],tc_src[8]; +}; + +int egl_initialize(EGLDisplay *dpy, EGLConfig *config, EGLContext *context); +void egl_destroy(EGLDisplay dpy, EGLContext context); + +#define ENTER() printf("enter %s\n",__FUNCTION__) +#define LEAVE() printf("leave %s\n",__FUNCTION__) +#define FAIL() printf("fail %s\n",__FUNCTION__) + +#ifdef DEBUG +#define DBG(...) do { \ + fprintf(stderr, __VA_ARGS__); \ +} while (0) +#else +#define DBG(...) +#endif + +#endif /* __GL_RENDER_H__ */