Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- diff -rupN Mesa-10.0.2-orig/src/glx/glxcmds.c Mesa-10.0.2-new/src/glx/glxcmds.c
- --- Mesa-10.0.2-orig/src/glx/glxcmds.c 2014-01-09 11:44:52.000000000 -0800
- +++ Mesa-10.0.2-new/src/glx/glxcmds.c 2014-04-15 11:28:16.185976811 -0700
- @@ -38,6 +38,7 @@
- #include "glxextensions.h"
- #include "indirect.h"
- #include "glx_error.h"
- +#include "glxzodiac.h"
- #ifdef GLX_DIRECT_RENDERING
- #ifdef GLX_USE_APPLEGL
- @@ -454,6 +455,7 @@ _X_EXPORT void
- glXDestroyContext(Display * dpy, GLXContext ctx)
- {
- struct glx_context *gc = (struct glx_context *) ctx;
- + glxzodiac_producer_free_yuy2();
- if (gc == NULL || gc->xid == None)
- return;
- @@ -811,6 +813,7 @@ glXDestroyGLXPixmap(Display * dpy, GLXPi
- _X_EXPORT void
- glXSwapBuffers(Display * dpy, GLXDrawable drawable)
- {
- + glxzodiac_capture_frame(dpy, drawable);
- #ifdef GLX_USE_APPLEGL
- struct glx_context * gc = __glXGetCurrentContext();
- if(gc && apple_glx_is_current_drawable(dpy, gc->driContext, drawable)) {
- diff -rupN Mesa-10.0.2-orig/src/glx/glxzodiac.c Mesa-10.0.2-new/src/glx/glxzodiac.c
- --- Mesa-10.0.2-orig/src/glx/glxzodiac.c 1969-12-31 16:00:00.000000000 -0800
- +++ Mesa-10.0.2-new/src/glx/glxzodiac.c 2014-04-15 11:28:16.185976811 -0700
- @@ -0,0 +1,320 @@
- +/*
- + * Copyright (C) 2014 Kernel Labs 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, 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
- + * THE AUTHORS OR COPYRIGHT HOLDERS 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 <libipcvideo/ipcvideo.h>
- +
- +#include <stdlib.h> /* getenv */
- +#include <string.h> /* memset */
- +#include <libyuv.h> /* Colorspace conversion */
- +
- +#include "glxzodiac.h"
- +
- +static struct ipcvideo_s *ctx = 0;
- +
- +static struct zodiac_stats_s {
- + struct timeval lastFramePush;
- +} zodiac_stats;
- +
- +/* The IPC mechanism is disabled by default, opt in by using an environment variable
- + * if you want all GL frames to be sent to the ipc sharing mechanism.
- + */
- +static int ipcvideo_enable = 0;
- +static int ipcvideo_debug = 0;
- +static int ipcvideo_buffers = 4;
- +static int ipcvideo_dropfps = 30; /* Drop frames delivered fast than nFPS */
- +static double ipcvideo_dropms = (1000 / 30);
- +#define dprintf(level, fmt, arg...)\
- + do { if (ipcvideo_debug >= level)\
- + printf("libglx:" fmt, ## arg);\
- + } while (0)
- +
- +static double zodiac_measureNow(struct zodiac_stats_s *s)
- +{
- + struct timeval now;
- + gettimeofday(&now, 0);
- +#if 0
- + /* Generally, uncomment this to show the incoming frame times for all frames. */
- + printf("%d.%d\n", now.tv_sec, now.tv_usec);
- +#endif
- + double elapsedTime = (now.tv_sec - s->lastFramePush.tv_sec) * 1000.0; /* sec to ms */
- + elapsedTime += (now.tv_usec - s->lastFramePush.tv_usec) / 1000.0; /* us to ms */
- +
- + return elapsedTime;
- +}
- +
- +/* Allocate a YUY2 video pipe based on the given pixel resolution */
- +int glxzodiac_producer_alloc_yuy2(int width, int height, int depth, int stride)
- +{
- + char *p = getenv("ZODIAC_IPC_ENABLE");
- + if (p) {
- + ipcvideo_enable = atoi(p);
- + }
- +
- + p = getenv("ZODIAC_IPC_DEBUG");
- + if (p) {
- + ipcvideo_debug = atoi(p);
- + }
- +
- + p = getenv("ZODIAC_IPC_DROPFPS");
- + if (p) {
- + ipcvideo_dropfps = atoi(p);
- + ipcvideo_dropms = (double)1000 / (double)ipcvideo_dropfps;
- + }
- +
- + p = getenv("ZODIAC_IPC_BUFFERS");
- + if (p) {
- + ipcvideo_buffers = atoi(p);
- + }
- +
- + dprintf(1, "%s(%d, %d, %d, %d, fps=%d timeout=%f) ipcvideo_enable = %d\n",
- + __func__, width, height, depth, stride, ipcvideo_dropfps, ipcvideo_dropms, ipcvideo_enable);
- + if (!ipcvideo_enable)
- + return -1;
- +
- + if ((stride != (width * depth)) || (depth < 1) || (depth > 4) || (!width) || (!height))
- + return -1; /* We don't support strides, do some basic arg checks */
- +
- + if (ctx)
- + return -1; /* Already initialized */
- +
- + dprintf(0, "%s() Environment variables:\n", __func__);
- + dprintf(0, "%s() ZODIAC_IPC_ENABLE=%d\n", __func__, ipcvideo_enable);
- + dprintf(0, "%s() ZODIAC_IPC_DEBUG=%d\n", __func__, ipcvideo_debug);
- + dprintf(0, "%s() ZODIAC_IPC_DROPFPS=%d\n", __func__, ipcvideo_dropfps);
- +
- + int ret = ipcvideo_context_create(&ctx);
- + if (KLAPI_FAILED(ret)) {
- + printf("Failed to create a context\n");
- + return -1;
- + }
- +
- + /* Attach to a segment to our context, get its working dimensions */
- + struct ipcvideo_dimensions_s d;
- + ret = ipcvideo_context_attach(ctx, 1999, "/tmp", &d);
- + if (KLAPI_FAILED(ret)) {
- + dprintf(1, "Unable to attach to segment, creating it.\n");
- +
- + /* Create the dimensions and segment */
- + d.width = width;
- + d.height = height;
- + d.depth = 2;
- + d.stride = width * 2;
- + d.fourcc = IPCFOURCC_YUYV;
- + ret = ipcvideo_context_prepare(ctx, 1999, "/tmp", &d, ipcvideo_buffers);
- + if (KLAPI_FAILED(ret)) {
- + printf("Unable to prepare segment err = %d, aborting.\n", ret);
- + if (ret == KLAPI_NO_RESOURCE)
- + printf("Increase shmax is larger enough to hold all your buffers (%d)\n", ipcvideo_buffers);
- + }
- + }
- +
- + ipcvideo_dump_context(ctx);
- + ipcvideo_dump_metadata(ctx);
- + ipcvideo_dump_buffers(ctx);
- +
- + return 0;
- +}
- +
- +int glxzodiac_producer_push_argb(int width, int height, int depth, int stride, unsigned char *srcpixels)
- +{
- + if (!ipcvideo_enable)
- + return 0;
- +
- + if (!ctx)
- + return -1; /* Not initialized */
- +
- + dprintf(1, "%s(%d, %d, %d, %d, %p)\n", __func__, width, height, depth, stride, srcpixels);
- +
- + if ((!srcpixels) || (stride != (width * depth)) || (depth < 1) || (depth > 4) || (!width) || (!height))
- + return -1; /* We don't support strides, do some basic arg checks */
- +
- + int freeBuffer = 1;
- +
- + struct ipcvideo_buffer_s *buf = 0;
- + int ret = ipcvideo_list_free_dequeue(ctx, &buf);
- + if (KLAPI_FAILED(ret)) {
- + /* Free list has stalled? Pop the busy list and use it */
- + ret = ipcvideo_list_busy_dequeue(ctx, &buf);
- + if (KLAPI_FAILED(ret))
- + return -1;
- +
- + freeBuffer = 0;
- + }
- +
- + unsigned char *pixels;
- + unsigned int length;
- + ret = ipcvideo_buffer_get_data(ctx, buf, &pixels, &length);
- + if (KLAPI_FAILED(ret)) {
- + ipcvideo_list_free_enqueue(ctx, buf);
- + return -1;
- + }
- +
- + dprintf(1, "Got %s buffer %p length %x [ %02x %02x %02x %02x ]\n",
- + freeBuffer ? "free" : "recycled busy",
- + pixels, length,
- + *(pixels + 0),
- + *(pixels + 1),
- + *(pixels + 2),
- + *(pixels + 3));
- +
- + /* Fill the buffer with pixels */
- +
- + /* have the highly efficently CSC (SSE2/SSE3) correct the inverted image
- + * during colorspace conversion from ARGB to YUY2, saving the memcpy.
- + */
- + int r = ARGBToYUY2(
- + srcpixels, // Source material
- + stride, // src_stride_argb * bytes per pixel
- + pixels, // dst buffer
- + width * 2, // dst_stride_yuy2
- + width, // source width
- + height * -1 // source height -1 (invert vertically)
- + );
- + if (r < 0)
- + dprintf(0, "%s() Colorspace conversion error\n", __func__);
- +
- + ipcvideo_list_busy_enqueue(ctx, buf);
- +
- + return 0;
- +}
- +
- +int glxzodiac_producer_free_yuy2(void)
- +{
- + if (!ipcvideo_enable)
- + return 0;
- + if (!ctx)
- + return -1; /* Not initialized */
- +
- + dprintf(1, "libglx:%s()\n", __func__);
- +
- + int ret = ipcvideo_context_detach(ctx);
- + if (KLAPI_FAILED(ret))
- + printf("Unable to detach err = %d, aborting.\n", ret);
- +
- + ret = ipcvideo_context_destroy(ctx);
- + if (KLAPI_FAILED(ret)) {
- + printf("Failed to destroy a context\n");
- + return -1;
- + }
- +
- + return 0;
- +}
- +
- +/*
- + * Don't burden the glXSwapBuffer call with memcpys and
- + * colorspace conversion if the frame rate is too high.
- + *
- + * OpenGL will call us during the glXSwapBuffers() context.
- + * If we're being called faster than 15FPS theb simply return.
- + * otherwise, get the pixel data in RGBA format, and push it
- + * into the IPC pipeline (which will implicitly colorspace
- + * convert to YUY2).
- + *
- + */
- +int glxzodiac_capture_frame(Display *dpy, GLXDrawable drawable)
- +{
- + /* Throw away the frame if the app swapping buffers (generate frames)
- + * faster than N milliseconds. Reqmnt: We want to limit input into the pipe.
- + * Some comments worth bearing in mind:
- + * 1. If the opengl app is running at 60fps, swapBuffers() will be called every 16.7ms.
- + * 2. If our capture layer is targetting 30fps, then we calculate a droptimeout of 1000 / 30 = 33.3ms
- + * We'll actively look for a frame every 33ms.
- + * Frames will arrive with the following relative times:
- + * #1 - 0ms - This will be used
- + * #2 - 16.7ms - dropped (last frame was 16.7ms < 33.3ms).
- + * #3 - 33.4ms - This will be used
- + * #3 - 50.1ms - dropped (last frame was 16.7ms < 33.3ms).
- + * This would result in 30fps.
- + * However, gltest pushed frames at 61-62 fps, so the math works out that we drop
- + * one in three frames, resulting in 20fps. Grrr
- + *
- + * As a result, suggest the DROPFPS rate is adjusted with considered to the input fps.
- + * ZODIAC_IPC_DROPFPS with the gltest app running at 61.5 fps generally produces between 29
- + * to 34fps into the pipeline, measureabkle with metadata-demo or the osd.
- + */
- + double elapsedMS = zodiac_measureNow(&zodiac_stats);
- + if (elapsedMS <= ipcvideo_dropms) {
- + dprintf(3, "%s() dropping frame because last frame was %fMS ago. (%f <= %f)\n",
- + __func__, elapsedMS,
- + elapsedMS, ipcvideo_dropms);
- + return 0;
- + }
- + /* Update the last good frame timestamp */
- + gettimeofday(&zodiac_stats.lastFramePush, 0);
- +
- + /* We need the window size */
- + XWindowAttributes attr;
- + XGetWindowAttributes(dpy, drawable, &attr);
- + dprintf(1, "%s() width = %d height = %d depth = %d (pixels)\n",
- + __func__,
- + attr.width,
- + attr.height,
- + attr.depth);
- +
- + /* TODO: The depth attribute is reported as 24bits during testing,
- + * when we know the source material on the GL surface is
- + * 32bit ABGR. This is the X11 depth vs the GL depth. Hardcode
- + * the GL depth to 4 bytes, I can't find it anywhere else.
- + */
- + int depth = 4;
- + int len = attr.width * attr.height * depth;
- + int stride = attr.width * depth;
- +
- + /* We need a temporary buffer for the readPixels call(), build it once */
- + static unsigned char *dst = 0;
- + if (dst == 0) {
- + dst = calloc(1, len);
- +
- + /* Initialize the video pipe if it hasn't already been done. */
- + glxzodiac_producer_alloc_yuy2(attr.width, attr.height, depth, stride);
- + }
- +
- + /* Cache GL context */
- + glPushAttrib(GL_PIXEL_MODE_BIT);
- + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
- +
- + GLenum capture_buffer = GL_FRONT;
- + glReadBuffer(capture_buffer);
- +
- + GLint pack_alignment = 8;
- + glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment);
- +
- + glReadPixels(
- + 0, /* origin X */
- + 0, /* origin Y */
- + attr.width, /* width */
- + attr.height, /* height */
- + GL_BGRA, /* 4 byte depth */
- + GL_UNSIGNED_BYTE,
- + dst /* output pixel buffer*/
- + );
- +
- + int ret = glxzodiac_producer_push_argb(attr.width, attr.height, depth, stride, dst);
- + if (KLAPI_SUCCESS(ret)) {
- + }
- +
- + /* Restore GL context */
- + glPopClientAttrib();
- + glPopAttrib();
- +
- + return 0;
- +}
- diff -rupN Mesa-10.0.2-orig/src/glx/glxzodiac.h Mesa-10.0.2-new/src/glx/glxzodiac.h
- --- Mesa-10.0.2-orig/src/glx/glxzodiac.h 1969-12-31 16:00:00.000000000 -0800
- +++ Mesa-10.0.2-new/src/glx/glxzodiac.h 2014-04-15 11:28:16.185976811 -0700
- @@ -0,0 +1,50 @@
- +/*
- + * Mesa 3-D graphics library
- + *
- + * Copyright (C) 2014 Kernel Labs 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, 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
- + * THE AUTHORS OR COPYRIGHT HOLDERS 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 GLXZODIAC_H
- +#define GLXZODIAC_H
- +
- +#include "glxclient.h"
- +#include "glapi.h"
- +#include "glxextensions.h"
- +#include "indirect.h"
- +#include "glx_error.h"
- +#include "glxzodiac.h"
- +
- +/* Environment variables:
- + *
- + * ZODIAC_IPC_ENABLE=0|1 (def: 0. Set to 1 to enable the IPC mechanism)
- + * ZODIAC_IPC_DEBUG=N (def: 0. Raise higher than 0 to enable verbose output)
- + * ZODIAC_IPC_DROPFPS=N (def: 30. Drop frames that are delivered fast than this are dropped)
- + * ZODIAC_IPC_BUFFERS=N (def: 4. Number of frames allocated for list use)
- + */
- +
- +int glxzodiac_producer_alloc_yuy2(int width, int height, int depth, int stride);
- +int glxzodiac_producer_push_argb(int width, int height, int depth, int stride, unsigned char *buf);
- +int glxzodiac_producer_free_yuy2(void);
- +
- +int glxzodiac_capture_frame(Display *dpy, GLXDrawable drawable);
- +
- +#endif
- diff -rupN Mesa-10.0.2-orig/src/glx/Makefile.am Mesa-10.0.2-new/src/glx/Makefile.am
- --- Mesa-10.0.2-orig/src/glx/Makefile.am 2014-01-09 11:44:52.000000000 -0800
- +++ Mesa-10.0.2-new/src/glx/Makefile.am 2014-04-15 11:28:19.789890766 -0700
- @@ -81,6 +81,7 @@ libglx_la_SOURCES = \
- render2.c \
- renderpix.c \
- single2.c \
- + glxzodiac.c \
- singlepix.c \
- vertarr.c \
- xfont.c \
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement