1 /**************************************************************************
3 * Copyright 2011 Jose Fonseca
6 * Permission is hereby granted, free of charge, to any person obtaining a copy
7 * of this software and associated documentation files (the "Software"), to deal
8 * in the Software without restriction, including without limitation the rights
9 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
10 * copies of the Software, and to permit persons to whom the Software is
11 * furnished to do so, subject to the following conditions:
13 * The above copyright notice and this permission notice shall be included in
14 * all copies or substantial portions of the Software.
16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
17 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
18 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
19 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
20 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
21 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
24 **************************************************************************/
30 #include "os_path.hpp"
36 #if !defined(TRACE_EGL) && !defined(_WIN32) && !defined(__APPLE__)
39 #include <X11/Xproto.h>
43 errorHandler(Display *display, XErrorEvent *event)
45 if (event->error_code == BadDrawable &&
46 event->request_code == X_GetGeometry) {
51 XGetErrorText(display, event->error_code, error_text, sizeof error_text);
52 fprintf(stderr, "X Error of failed request: %s\n", error_text);
58 #endif /* !_WIN32 && !__APPLE__ */
61 namespace glsnapshot {
65 * Get the contents of the current drawable into an image.
68 getDrawableImage(void) {
69 #if defined(TRACE_EGL)
76 HDC hDC = __wglGetCurrentDC();
81 HWND hWnd = WindowFromDC(hDC);
84 if (!GetClientRect(hWnd, &rect)) {
88 int width = rect.right - rect.left;
89 int height = rect.bottom - rect.top;
91 // TODO: http://msdn.microsoft.com/en-us/library/dd183402
95 #elif defined(__APPLE__)
106 unsigned int w, h, bw, depth;
111 display = __glXGetCurrentDisplay();
116 drawable = __glXGetCurrentDrawable();
117 if (drawable == None) {
122 * XXX: This does not work for drawables created with glXCreateWindow
125 int (*oldErrorHandler)(Display *, XErrorEvent *);
128 oldErrorHandler = XSetErrorHandler(errorHandler);
129 status = XGetGeometry(display, drawable, &root, &x, &y, &w, &h, &bw, &depth);
130 XSetErrorHandler(oldErrorHandler);
137 ximage = XGetImage(display, drawable, 0, 0, w, h, AllPlanes, ZPixmap);
142 image::Image *image = NULL;
144 if (ximage->depth == 24 &&
145 ximage->bits_per_pixel == 32 &&
146 ximage->red_mask == 0x00ff0000 &&
147 ximage->green_mask == 0x0000ff00 &&
148 ximage->blue_mask == 0x000000ff) {
150 image = new image::Image(w, h, 4);
153 const uint32_t *src = (const uint32_t *)ximage->data;
154 uint32_t *dst = (uint32_t*) image->start();
155 for (unsigned y = 0; y < h; ++y) {
156 for (unsigned x = 0; x < w; ++x) {
157 uint32_t bgra = src[x];
158 uint32_t rgba = (bgra & 0xff00ff00)
159 | ((bgra >> 16) & 0xff)
160 | ((bgra & 0xff) << 16);
164 src += ximage->bytes_per_line / sizeof *src;
165 dst += image->stride() / sizeof *src;
169 os::log("apitrace: unexpected XImage: "
170 "bits_per_pixel = %i, "
172 "red_mask = 0x%08lx, "
173 "green_mask = 0x%08lx, "
174 "blue_mask = 0x%08lx\n",
175 ximage->bits_per_pixel,
182 XDestroyImage(ximage);
189 // Prefix of the snapshot images to take, if not NULL.
190 static const char *snapshot_prefix = NULL;
192 // Maximum number of frames to trace.
193 static unsigned max_frames = ~0;
195 // Current frame number.
196 static unsigned frame_no = 0;
199 void snapshot(unsigned call_no) {
202 const char *max_frames_str = getenv("TRACE_FRAMES");
203 if (max_frames_str) {
204 max_frames = atoi(max_frames_str);
206 snapshot_prefix = getenv("TRACE_SNAPSHOT");
211 if (snapshot_prefix) {
212 image::Image *src = getDrawableImage();
214 os::Path filename = os::Path::format("%s%010u.png", snapshot_prefix, call_no);
215 if (src->writePNG(filename)) {
216 os::log("apitrace: wrote %s\n", filename.str());
223 if (frame_no >= max_frames) {
229 } /* namespace glsnapshot */