Advertisement
Guest User

Untitled

a guest
Apr 21st, 2014
86
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 14.43 KB | None | 0 0
  1. diff -rupN Mesa-10.0.2-orig/src/glx/glxcmds.c Mesa-10.0.2-new/src/glx/glxcmds.c
  2. --- Mesa-10.0.2-orig/src/glx/glxcmds.c 2014-01-09 11:44:52.000000000 -0800
  3. +++ Mesa-10.0.2-new/src/glx/glxcmds.c 2014-04-15 11:28:16.185976811 -0700
  4. @@ -38,6 +38,7 @@
  5. #include "glxextensions.h"
  6. #include "indirect.h"
  7. #include "glx_error.h"
  8. +#include "glxzodiac.h"
  9.  
  10. #ifdef GLX_DIRECT_RENDERING
  11. #ifdef GLX_USE_APPLEGL
  12. @@ -454,6 +455,7 @@ _X_EXPORT void
  13. glXDestroyContext(Display * dpy, GLXContext ctx)
  14. {
  15. struct glx_context *gc = (struct glx_context *) ctx;
  16. + glxzodiac_producer_free_yuy2();
  17.  
  18. if (gc == NULL || gc->xid == None)
  19. return;
  20. @@ -811,6 +813,7 @@ glXDestroyGLXPixmap(Display * dpy, GLXPi
  21. _X_EXPORT void
  22. glXSwapBuffers(Display * dpy, GLXDrawable drawable)
  23. {
  24. + glxzodiac_capture_frame(dpy, drawable);
  25. #ifdef GLX_USE_APPLEGL
  26. struct glx_context * gc = __glXGetCurrentContext();
  27. if(gc && apple_glx_is_current_drawable(dpy, gc->driContext, drawable)) {
  28. diff -rupN Mesa-10.0.2-orig/src/glx/glxzodiac.c Mesa-10.0.2-new/src/glx/glxzodiac.c
  29. --- Mesa-10.0.2-orig/src/glx/glxzodiac.c 1969-12-31 16:00:00.000000000 -0800
  30. +++ Mesa-10.0.2-new/src/glx/glxzodiac.c 2014-04-15 11:28:16.185976811 -0700
  31. @@ -0,0 +1,320 @@
  32. +/*
  33. + * Copyright (C) 2014 Kernel Labs Inc. All Rights Reserved.
  34. + *
  35. + * Permission is hereby granted, free of charge, to any person obtaining a
  36. + * copy of this software and associated documentation files (the "Software"),
  37. + * to deal in the Software without restriction, including without limitation
  38. + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  39. + * and/or sell copies of the Software, and to permit persons to whom the
  40. + * Software is furnished to do so, subject to the following conditions:
  41. + *
  42. + * The above copyright notice and this permission notice shall be included
  43. + * in all copies or substantial portions of the Software.
  44. + *
  45. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  46. + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  47. + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  48. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  49. + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  50. + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  51. + * OTHER DEALINGS IN THE SOFTWARE.
  52. + */
  53. +
  54. +#include <libipcvideo/ipcvideo.h>
  55. +
  56. +#include <stdlib.h> /* getenv */
  57. +#include <string.h> /* memset */
  58. +#include <libyuv.h> /* Colorspace conversion */
  59. +
  60. +#include "glxzodiac.h"
  61. +
  62. +static struct ipcvideo_s *ctx = 0;
  63. +
  64. +static struct zodiac_stats_s {
  65. + struct timeval lastFramePush;
  66. +} zodiac_stats;
  67. +
  68. +/* The IPC mechanism is disabled by default, opt in by using an environment variable
  69. + * if you want all GL frames to be sent to the ipc sharing mechanism.
  70. + */
  71. +static int ipcvideo_enable = 0;
  72. +static int ipcvideo_debug = 0;
  73. +static int ipcvideo_buffers = 4;
  74. +static int ipcvideo_dropfps = 30; /* Drop frames delivered fast than nFPS */
  75. +static double ipcvideo_dropms = (1000 / 30);
  76. +#define dprintf(level, fmt, arg...)\
  77. + do { if (ipcvideo_debug >= level)\
  78. + printf("libglx:" fmt, ## arg);\
  79. + } while (0)
  80. +
  81. +static double zodiac_measureNow(struct zodiac_stats_s *s)
  82. +{
  83. + struct timeval now;
  84. + gettimeofday(&now, 0);
  85. +#if 0
  86. + /* Generally, uncomment this to show the incoming frame times for all frames. */
  87. + printf("%d.%d\n", now.tv_sec, now.tv_usec);
  88. +#endif
  89. + double elapsedTime = (now.tv_sec - s->lastFramePush.tv_sec) * 1000.0; /* sec to ms */
  90. + elapsedTime += (now.tv_usec - s->lastFramePush.tv_usec) / 1000.0; /* us to ms */
  91. +
  92. + return elapsedTime;
  93. +}
  94. +
  95. +/* Allocate a YUY2 video pipe based on the given pixel resolution */
  96. +int glxzodiac_producer_alloc_yuy2(int width, int height, int depth, int stride)
  97. +{
  98. + char *p = getenv("ZODIAC_IPC_ENABLE");
  99. + if (p) {
  100. + ipcvideo_enable = atoi(p);
  101. + }
  102. +
  103. + p = getenv("ZODIAC_IPC_DEBUG");
  104. + if (p) {
  105. + ipcvideo_debug = atoi(p);
  106. + }
  107. +
  108. + p = getenv("ZODIAC_IPC_DROPFPS");
  109. + if (p) {
  110. + ipcvideo_dropfps = atoi(p);
  111. + ipcvideo_dropms = (double)1000 / (double)ipcvideo_dropfps;
  112. + }
  113. +
  114. + p = getenv("ZODIAC_IPC_BUFFERS");
  115. + if (p) {
  116. + ipcvideo_buffers = atoi(p);
  117. + }
  118. +
  119. + dprintf(1, "%s(%d, %d, %d, %d, fps=%d timeout=%f) ipcvideo_enable = %d\n",
  120. + __func__, width, height, depth, stride, ipcvideo_dropfps, ipcvideo_dropms, ipcvideo_enable);
  121. + if (!ipcvideo_enable)
  122. + return -1;
  123. +
  124. + if ((stride != (width * depth)) || (depth < 1) || (depth > 4) || (!width) || (!height))
  125. + return -1; /* We don't support strides, do some basic arg checks */
  126. +
  127. + if (ctx)
  128. + return -1; /* Already initialized */
  129. +
  130. + dprintf(0, "%s() Environment variables:\n", __func__);
  131. + dprintf(0, "%s() ZODIAC_IPC_ENABLE=%d\n", __func__, ipcvideo_enable);
  132. + dprintf(0, "%s() ZODIAC_IPC_DEBUG=%d\n", __func__, ipcvideo_debug);
  133. + dprintf(0, "%s() ZODIAC_IPC_DROPFPS=%d\n", __func__, ipcvideo_dropfps);
  134. +
  135. + int ret = ipcvideo_context_create(&ctx);
  136. + if (KLAPI_FAILED(ret)) {
  137. + printf("Failed to create a context\n");
  138. + return -1;
  139. + }
  140. +
  141. + /* Attach to a segment to our context, get its working dimensions */
  142. + struct ipcvideo_dimensions_s d;
  143. + ret = ipcvideo_context_attach(ctx, 1999, "/tmp", &d);
  144. + if (KLAPI_FAILED(ret)) {
  145. + dprintf(1, "Unable to attach to segment, creating it.\n");
  146. +
  147. + /* Create the dimensions and segment */
  148. + d.width = width;
  149. + d.height = height;
  150. + d.depth = 2;
  151. + d.stride = width * 2;
  152. + d.fourcc = IPCFOURCC_YUYV;
  153. + ret = ipcvideo_context_prepare(ctx, 1999, "/tmp", &d, ipcvideo_buffers);
  154. + if (KLAPI_FAILED(ret)) {
  155. + printf("Unable to prepare segment err = %d, aborting.\n", ret);
  156. + if (ret == KLAPI_NO_RESOURCE)
  157. + printf("Increase shmax is larger enough to hold all your buffers (%d)\n", ipcvideo_buffers);
  158. + }
  159. + }
  160. +
  161. + ipcvideo_dump_context(ctx);
  162. + ipcvideo_dump_metadata(ctx);
  163. + ipcvideo_dump_buffers(ctx);
  164. +
  165. + return 0;
  166. +}
  167. +
  168. +int glxzodiac_producer_push_argb(int width, int height, int depth, int stride, unsigned char *srcpixels)
  169. +{
  170. + if (!ipcvideo_enable)
  171. + return 0;
  172. +
  173. + if (!ctx)
  174. + return -1; /* Not initialized */
  175. +
  176. + dprintf(1, "%s(%d, %d, %d, %d, %p)\n", __func__, width, height, depth, stride, srcpixels);
  177. +
  178. + if ((!srcpixels) || (stride != (width * depth)) || (depth < 1) || (depth > 4) || (!width) || (!height))
  179. + return -1; /* We don't support strides, do some basic arg checks */
  180. +
  181. + int freeBuffer = 1;
  182. +
  183. + struct ipcvideo_buffer_s *buf = 0;
  184. + int ret = ipcvideo_list_free_dequeue(ctx, &buf);
  185. + if (KLAPI_FAILED(ret)) {
  186. + /* Free list has stalled? Pop the busy list and use it */
  187. + ret = ipcvideo_list_busy_dequeue(ctx, &buf);
  188. + if (KLAPI_FAILED(ret))
  189. + return -1;
  190. +
  191. + freeBuffer = 0;
  192. + }
  193. +
  194. + unsigned char *pixels;
  195. + unsigned int length;
  196. + ret = ipcvideo_buffer_get_data(ctx, buf, &pixels, &length);
  197. + if (KLAPI_FAILED(ret)) {
  198. + ipcvideo_list_free_enqueue(ctx, buf);
  199. + return -1;
  200. + }
  201. +
  202. + dprintf(1, "Got %s buffer %p length %x [ %02x %02x %02x %02x ]\n",
  203. + freeBuffer ? "free" : "recycled busy",
  204. + pixels, length,
  205. + *(pixels + 0),
  206. + *(pixels + 1),
  207. + *(pixels + 2),
  208. + *(pixels + 3));
  209. +
  210. + /* Fill the buffer with pixels */
  211. +
  212. + /* have the highly efficently CSC (SSE2/SSE3) correct the inverted image
  213. + * during colorspace conversion from ARGB to YUY2, saving the memcpy.
  214. + */
  215. + int r = ARGBToYUY2(
  216. + srcpixels, // Source material
  217. + stride, // src_stride_argb * bytes per pixel
  218. + pixels, // dst buffer
  219. + width * 2, // dst_stride_yuy2
  220. + width, // source width
  221. + height * -1 // source height -1 (invert vertically)
  222. + );
  223. + if (r < 0)
  224. + dprintf(0, "%s() Colorspace conversion error\n", __func__);
  225. +
  226. + ipcvideo_list_busy_enqueue(ctx, buf);
  227. +
  228. + return 0;
  229. +}
  230. +
  231. +int glxzodiac_producer_free_yuy2(void)
  232. +{
  233. + if (!ipcvideo_enable)
  234. + return 0;
  235. + if (!ctx)
  236. + return -1; /* Not initialized */
  237. +
  238. + dprintf(1, "libglx:%s()\n", __func__);
  239. +
  240. + int ret = ipcvideo_context_detach(ctx);
  241. + if (KLAPI_FAILED(ret))
  242. + printf("Unable to detach err = %d, aborting.\n", ret);
  243. +
  244. + ret = ipcvideo_context_destroy(ctx);
  245. + if (KLAPI_FAILED(ret)) {
  246. + printf("Failed to destroy a context\n");
  247. + return -1;
  248. + }
  249. +
  250. + return 0;
  251. +}
  252. +
  253. +/*
  254. + * Don't burden the glXSwapBuffer call with memcpys and
  255. + * colorspace conversion if the frame rate is too high.
  256. + *
  257. + * OpenGL will call us during the glXSwapBuffers() context.
  258. + * If we're being called faster than 15FPS theb simply return.
  259. + * otherwise, get the pixel data in RGBA format, and push it
  260. + * into the IPC pipeline (which will implicitly colorspace
  261. + * convert to YUY2).
  262. + *
  263. + */
  264. +int glxzodiac_capture_frame(Display *dpy, GLXDrawable drawable)
  265. +{
  266. + /* Throw away the frame if the app swapping buffers (generate frames)
  267. + * faster than N milliseconds. Reqmnt: We want to limit input into the pipe.
  268. + * Some comments worth bearing in mind:
  269. + * 1. If the opengl app is running at 60fps, swapBuffers() will be called every 16.7ms.
  270. + * 2. If our capture layer is targetting 30fps, then we calculate a droptimeout of 1000 / 30 = 33.3ms
  271. + * We'll actively look for a frame every 33ms.
  272. + * Frames will arrive with the following relative times:
  273. + * #1 - 0ms - This will be used
  274. + * #2 - 16.7ms - dropped (last frame was 16.7ms < 33.3ms).
  275. + * #3 - 33.4ms - This will be used
  276. + * #3 - 50.1ms - dropped (last frame was 16.7ms < 33.3ms).
  277. + * This would result in 30fps.
  278. + * However, gltest pushed frames at 61-62 fps, so the math works out that we drop
  279. + * one in three frames, resulting in 20fps. Grrr
  280. + *
  281. + * As a result, suggest the DROPFPS rate is adjusted with considered to the input fps.
  282. + * ZODIAC_IPC_DROPFPS with the gltest app running at 61.5 fps generally produces between 29
  283. + * to 34fps into the pipeline, measureabkle with metadata-demo or the osd.
  284. + */
  285. + double elapsedMS = zodiac_measureNow(&zodiac_stats);
  286. + if (elapsedMS <= ipcvideo_dropms) {
  287. + dprintf(3, "%s() dropping frame because last frame was %fMS ago. (%f <= %f)\n",
  288. + __func__, elapsedMS,
  289. + elapsedMS, ipcvideo_dropms);
  290. + return 0;
  291. + }
  292. + /* Update the last good frame timestamp */
  293. + gettimeofday(&zodiac_stats.lastFramePush, 0);
  294. +
  295. + /* We need the window size */
  296. + XWindowAttributes attr;
  297. + XGetWindowAttributes(dpy, drawable, &attr);
  298. + dprintf(1, "%s() width = %d height = %d depth = %d (pixels)\n",
  299. + __func__,
  300. + attr.width,
  301. + attr.height,
  302. + attr.depth);
  303. +
  304. + /* TODO: The depth attribute is reported as 24bits during testing,
  305. + * when we know the source material on the GL surface is
  306. + * 32bit ABGR. This is the X11 depth vs the GL depth. Hardcode
  307. + * the GL depth to 4 bytes, I can't find it anywhere else.
  308. + */
  309. + int depth = 4;
  310. + int len = attr.width * attr.height * depth;
  311. + int stride = attr.width * depth;
  312. +
  313. + /* We need a temporary buffer for the readPixels call(), build it once */
  314. + static unsigned char *dst = 0;
  315. + if (dst == 0) {
  316. + dst = calloc(1, len);
  317. +
  318. + /* Initialize the video pipe if it hasn't already been done. */
  319. + glxzodiac_producer_alloc_yuy2(attr.width, attr.height, depth, stride);
  320. + }
  321. +
  322. + /* Cache GL context */
  323. + glPushAttrib(GL_PIXEL_MODE_BIT);
  324. + glPushClientAttrib(GL_CLIENT_PIXEL_STORE_BIT);
  325. +
  326. + GLenum capture_buffer = GL_FRONT;
  327. + glReadBuffer(capture_buffer);
  328. +
  329. + GLint pack_alignment = 8;
  330. + glPixelStorei(GL_PACK_ALIGNMENT, pack_alignment);
  331. +
  332. + glReadPixels(
  333. + 0, /* origin X */
  334. + 0, /* origin Y */
  335. + attr.width, /* width */
  336. + attr.height, /* height */
  337. + GL_BGRA, /* 4 byte depth */
  338. + GL_UNSIGNED_BYTE,
  339. + dst /* output pixel buffer*/
  340. + );
  341. +
  342. + int ret = glxzodiac_producer_push_argb(attr.width, attr.height, depth, stride, dst);
  343. + if (KLAPI_SUCCESS(ret)) {
  344. + }
  345. +
  346. + /* Restore GL context */
  347. + glPopClientAttrib();
  348. + glPopAttrib();
  349. +
  350. + return 0;
  351. +}
  352. diff -rupN Mesa-10.0.2-orig/src/glx/glxzodiac.h Mesa-10.0.2-new/src/glx/glxzodiac.h
  353. --- Mesa-10.0.2-orig/src/glx/glxzodiac.h 1969-12-31 16:00:00.000000000 -0800
  354. +++ Mesa-10.0.2-new/src/glx/glxzodiac.h 2014-04-15 11:28:16.185976811 -0700
  355. @@ -0,0 +1,50 @@
  356. +/*
  357. + * Mesa 3-D graphics library
  358. + *
  359. + * Copyright (C) 2014 Kernel Labs Inc. All Rights Reserved.
  360. + *
  361. + * Permission is hereby granted, free of charge, to any person obtaining a
  362. + * copy of this software and associated documentation files (the "Software"),
  363. + * to deal in the Software without restriction, including without limitation
  364. + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
  365. + * and/or sell copies of the Software, and to permit persons to whom the
  366. + * Software is furnished to do so, subject to the following conditions:
  367. + *
  368. + * The above copyright notice and this permission notice shall be included
  369. + * in all copies or substantial portions of the Software.
  370. + *
  371. + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
  372. + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  373. + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
  374. + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
  375. + * OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
  376. + * ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
  377. + * OTHER DEALINGS IN THE SOFTWARE.
  378. + */
  379. +
  380. +
  381. +#ifndef GLXZODIAC_H
  382. +#define GLXZODIAC_H
  383. +
  384. +#include "glxclient.h"
  385. +#include "glapi.h"
  386. +#include "glxextensions.h"
  387. +#include "indirect.h"
  388. +#include "glx_error.h"
  389. +#include "glxzodiac.h"
  390. +
  391. +/* Environment variables:
  392. + *
  393. + * ZODIAC_IPC_ENABLE=0|1 (def: 0. Set to 1 to enable the IPC mechanism)
  394. + * ZODIAC_IPC_DEBUG=N (def: 0. Raise higher than 0 to enable verbose output)
  395. + * ZODIAC_IPC_DROPFPS=N (def: 30. Drop frames that are delivered fast than this are dropped)
  396. + * ZODIAC_IPC_BUFFERS=N (def: 4. Number of frames allocated for list use)
  397. + */
  398. +
  399. +int glxzodiac_producer_alloc_yuy2(int width, int height, int depth, int stride);
  400. +int glxzodiac_producer_push_argb(int width, int height, int depth, int stride, unsigned char *buf);
  401. +int glxzodiac_producer_free_yuy2(void);
  402. +
  403. +int glxzodiac_capture_frame(Display *dpy, GLXDrawable drawable);
  404. +
  405. +#endif
  406. diff -rupN Mesa-10.0.2-orig/src/glx/Makefile.am Mesa-10.0.2-new/src/glx/Makefile.am
  407. --- Mesa-10.0.2-orig/src/glx/Makefile.am 2014-01-09 11:44:52.000000000 -0800
  408. +++ Mesa-10.0.2-new/src/glx/Makefile.am 2014-04-15 11:28:19.789890766 -0700
  409. @@ -81,6 +81,7 @@ libglx_la_SOURCES = \
  410. render2.c \
  411. renderpix.c \
  412. single2.c \
  413. + glxzodiac.c \
  414. singlepix.c \
  415. vertarr.c \
  416. xfont.c \
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement