]> git.cworth.org Git - apitrace/blob - retrace/glretrace_glx.cpp
stash: Trace and replay of gnome-shell works
[apitrace] / retrace / glretrace_glx.cpp
1 /**************************************************************************
2  *
3  * Copyright 2011 Jose Fonseca
4  * All Rights Reserved.
5  *
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:
12  *
13  * The above copyright notice and this permission notice shall be included in
14  * all copies or substantial portions of the Software.
15  *
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
22  * THE SOFTWARE.
23  *
24  **************************************************************************/
25
26
27 #include "glproc.hpp"
28 #include "retrace.hpp"
29 #include "glretrace.hpp"
30
31 #include <vector>
32
33 #ifndef GLX_PBUFFER_HEIGHT
34 #define GLX_PBUFFER_HEIGHT 0x8040
35 #endif
36
37 #ifndef GLX_PBUFFER_WIDTH
38 #define GLX_PBUFFER_WIDTH 0x8041
39 #endif
40
41
42 using namespace glretrace;
43
44 typedef struct {
45     int width;
46     int height;
47     int depth;
48 } PixmapDesc;
49
50 typedef std::map<unsigned long, glws::Drawable *> DrawableMap;
51 typedef std::map<unsigned long long, Context *> ContextMap;
52 typedef std::map<unsigned long, PixmapDesc *> PixmapDescMap;
53 typedef std::map<GLXFBConfig, GLXFBConfig> ConfigMap;
54 typedef std::map<GLXFBConfig, std::vector<int> > ConfigAttribListMap;
55 static DrawableMap drawable_map;
56 static ContextMap context_map;
57 static PixmapDescMap pixmap_desc_map;
58 static ConfigMap config_map;
59 static ConfigAttribListMap config_attrib_list_map;
60
61 static glws::Drawable *
62 getDrawable(unsigned long drawable_id) {
63     if (drawable_id == 0) {
64         return NULL;
65     }
66
67     DrawableMap::const_iterator it;
68     it = drawable_map.find(drawable_id);
69     if (it == drawable_map.end()) {
70         return (drawable_map[drawable_id] = glretrace::createDrawable());
71     }
72
73     return it->second;
74 }
75
76 static Context *
77 getContext(unsigned long long context_ptr) {
78     if (context_ptr == 0) {
79         return NULL;
80     }
81
82     ContextMap::const_iterator it;
83     it = context_map.find(context_ptr);
84     if (it == context_map.end()) {
85         return (context_map[context_ptr] = glretrace::createContext());
86     }
87
88     return it->second;
89 }
90
91 static void retrace_glXCreateContext(trace::Call &call) {
92     unsigned long long orig_context = call.ret->toUIntPtr();
93     Context *share_context = getContext(call.arg(2).toUIntPtr());
94
95     Context *context = glretrace::createContext(share_context);
96     context_map[orig_context] = context;
97 }
98
99 static void retrace_glXCreateContextAttribsARB(trace::Call &call) {
100     unsigned long long orig_context = call.ret->toUIntPtr();
101     Context *share_context = getContext(call.arg(2).toUIntPtr());
102
103     Context *context = glretrace::createContext(share_context);
104     context_map[orig_context] = context;
105 }
106
107 static void retrace_glXMakeCurrent(trace::Call &call) {
108     glws::Drawable *new_drawable = getDrawable(call.arg(1).toUInt());
109     Context *new_context = getContext(call.arg(2).toUIntPtr());
110
111     glretrace::makeCurrent(call, new_drawable, new_context);
112 }
113
114
115 static void retrace_glXDestroyContext(trace::Call &call) {
116     Context *context = getContext(call.arg(1).toUIntPtr());
117
118     if (!context) {
119         return;
120     }
121
122     delete context;
123 }
124
125 static void retrace_glXSwapBuffers(trace::Call &call) {
126     glws::Drawable *drawable = getDrawable(call.arg(1).toUInt());
127
128     frame_complete(call);
129     if (retrace::doubleBuffer) {
130         if (drawable) {
131             drawable->swapBuffers();
132         }
133     } else {
134         glFlush();
135     }
136 }
137
138 static void retrace_glXCreateNewContext(trace::Call &call) {
139     unsigned long long orig_context = call.ret->toUIntPtr();
140     Context *share_context = getContext(call.arg(3).toUIntPtr());
141
142     Context *context = glretrace::createContext(share_context);
143     context_map[orig_context] = context;
144 }
145
146 static void retrace_glXCreatePbuffer(trace::Call &call) {
147     const trace::Value *attrib_list = dynamic_cast<const trace::Array *>(&call.arg(2));
148     int width = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_WIDTH, 0);
149     int height = glretrace::parseAttrib(attrib_list, GLX_PBUFFER_HEIGHT, 0);
150
151     unsigned long long orig_drawable = call.ret->toUInt();
152
153     glws::Drawable *drawable = glretrace::createPbuffer(width, height);
154     
155     drawable_map[orig_drawable] = drawable;
156 }
157
158 static void retrace_glXDestroyPbuffer(trace::Call &call) {
159     glws::Drawable *drawable = getDrawable(call.arg(1).toUInt());
160
161     if (!drawable) {
162         return;
163     }
164
165     delete drawable;
166 }
167
168 static void retrace_glXMakeContextCurrent(trace::Call &call) {
169     glws::Drawable *new_drawable = getDrawable(call.arg(1).toUInt());
170     Context *new_context = getContext(call.arg(3).toUIntPtr());
171
172     glretrace::makeCurrent(call, new_drawable, new_context);
173 }
174
175 static void retrace_glXCreateWindow(trace::Call &call) {
176     glws::Drawable *window = getDrawable(call.arg(2).toUInt());
177
178     glretrace::createWindow(window);
179 }
180
181 static void retrace_glXDestroyWindow(trace::Call &call) {
182     glws::Drawable *window = getDrawable(call.arg(1).toUInt());
183
184     glretrace::destroyWindow(window);
185 }
186
187 static void retrace_XCreatePixmap(trace::Call &call) {
188     unsigned pixmap_id = call.ret->toUInt();
189
190     PixmapDesc *desc = new(PixmapDesc);
191
192     desc->width = call.arg(2).toUInt();
193     desc->height = call.arg(3).toUInt();
194     desc->depth = call.arg(4).toUInt();
195
196     pixmap_desc_map[pixmap_id] = desc;
197 }
198
199 static void retrace_XFreePixmap(trace::Call &call) {
200     unsigned pixmap_id = call.arg(1).toUInt();
201     PixmapDescMap::iterator it;
202
203     it = pixmap_desc_map.find(pixmap_id);
204     delete it->second;
205     pixmap_desc_map.erase(it);
206 }
207
208 static void retrace_glXCreatePixmap(trace::Call &call) {
209     retrace::ScopedAllocator _allocator;
210     GLXFBConfig fbconfig, orig_fbconfig = (GLXFBConfig) call.arg(1).toPointer();
211     unsigned orig_pixmap = call.arg(2).toUInt();
212     unsigned orig_gl_pixmap = call.ret->toUInt();
213     PixmapDesc *desc = pixmap_desc_map[orig_pixmap];
214     glws::Drawable *pixmap, *gl_pixmap;
215
216     int *attrib_list;
217     attrib_list = static_cast<int *>(_allocator.alloc(&call.arg(3), sizeof *attrib_list));
218     if (attrib_list) {
219         const trace::Array *arg_list = dynamic_cast<const trace::Array *>(&call.arg(3));
220         for (size_t i = 0; i < arg_list->values.size(); i++) {
221             attrib_list[i] = (*arg_list->values[i]).toSInt();
222         }
223     }
224
225     fbconfig = config_map[orig_fbconfig];
226
227     if (! fbconfig) {
228         std::vector<int> *attrib_list = &config_attrib_list_map[orig_fbconfig];
229         attrib_list->push_back(0);
230         fbconfig = glretrace::chooseConfig(attrib_list->data());
231         if (fbconfig) {
232             config_map[orig_fbconfig] = fbconfig;
233         } else {
234             fprintf(stderr, "Error: Failed to find suitable fbconfig\n");
235         }
236     }
237
238     pixmap = glretrace::createPixmap(desc->width, desc->height, desc->depth);
239
240     gl_pixmap = glretrace::createGLPixmap(fbconfig, pixmap, desc->width, desc->height, attrib_list);
241
242     drawable_map[orig_pixmap] = pixmap;
243     drawable_map[orig_gl_pixmap] = gl_pixmap;
244 }
245
246 static void retrace_glXBindTexImageEXT(trace::Call &call) {
247     glws::Drawable *pixmap = getDrawable(call.arg(1).toUInt());
248
249     glretrace::bindTexImage(pixmap, call.arg(2).toSInt());
250 }
251
252 static void retrace_glXReleaseTexImageEXT(trace::Call &call) {
253     glws::Drawable *pixmap = getDrawable(call.arg(1).toUInt());
254
255     glretrace::releaseTexImage(pixmap, call.arg(2).toSInt());
256 }
257
258 static void retrace_glXCopySubBufferMESA(trace::Call &call) {
259     glws::Drawable *drawable = getDrawable(call.arg(1).toUInt());
260     int x, y, width, height;
261
262     x = call.arg(2).toSInt();
263     y = call.arg(3).toSInt();
264     width = call.arg(4).toSInt();
265     height = call.arg(5).toSInt();
266
267     glretrace::copySubBuffer(drawable, x, y, width, height);
268 }
269
270 static void retrace_PutImageData(trace::Call &call) {
271     glws::Drawable *drawable = getDrawable(call.arg(0).toUInt());
272     int width, height, depth, bits_per_pixel, bytes_per_line, byte_order;
273     char *data;
274
275     data = static_cast<char *>((call.arg(1)).toPointer());
276     width = call.arg(2).toSInt();
277     height = call.arg(3).toSInt();
278     depth = call.arg(4).toSInt();
279     bits_per_pixel = call.arg(5).toSInt();
280     bytes_per_line = call.arg(6).toSInt();
281     byte_order = call.arg(7).toSInt();
282
283     glretrace::putImageData(drawable, data, width, height, depth,
284                             bits_per_pixel, bytes_per_line, byte_order);
285 }
286
287 static void retrace_glXChooseFBConfig(trace::Call &call) {
288     retrace::ScopedAllocator _allocator;
289     int orig_nelements;
290     const trace::Array *orig_configs;
291     GLXFBConfig config;
292
293     int *attrib_list;
294     attrib_list = static_cast<int *>(_allocator.alloc(&call.arg(2), sizeof *attrib_list));
295     if (attrib_list) {
296         const trace::Array *arg_list = dynamic_cast<const trace::Array *>(&call.arg(2));
297         for (size_t i = 0; i < arg_list->values.size(); i++) {
298             attrib_list[i] = arg_list->values[i]->toSInt();
299         }
300     }   
301
302     orig_nelements = dynamic_cast<const trace::Array *>(&call.arg(3))->values[0]->toSInt();
303     orig_configs = dynamic_cast<const trace::Array *>(call.ret);
304
305     config = glretrace::chooseConfig(attrib_list);
306     for (size_t i = 0; i < orig_nelements; i++) {
307         config_map[static_cast<GLXFBConfig>(orig_configs->values[i]->toPointer())] = config;
308     }
309 }
310
311 static void retrace_glXGetFBConfigAttrib(trace::Call &call) {
312     GLXFBConfig config = static_cast<GLXFBConfig>(call.arg(1).toPointer());
313     int attribute = call.arg(2).toUInt();
314     int value = dynamic_cast<const trace::Array *>(&call.arg(3))->values[0]->toSInt();
315
316     std::vector<int> *attrib_list = &config_attrib_list_map[config];
317     attrib_list->push_back(attribute);
318     attrib_list->push_back(value);
319 }
320
321 const retrace::Entry glretrace::glx_callbacks[] = {
322     //{"glXBindChannelToWindowSGIX", &retrace_glXBindChannelToWindowSGIX},
323     //{"glXBindSwapBarrierNV", &retrace_glXBindSwapBarrierNV},
324     //{"glXBindSwapBarrierSGIX", &retrace_glXBindSwapBarrierSGIX},
325     {"glXBindTexImageEXT", &retrace_glXBindTexImageEXT},
326     //{"glXChannelRectSGIX", &retrace_glXChannelRectSGIX},
327     //{"glXChannelRectSyncSGIX", &retrace_glXChannelRectSyncSGIX},
328     {"glXChooseFBConfig", &retrace_glXChooseFBConfig},
329     {"glXChooseFBConfigSGIX", &retrace::ignore},
330     {"glXChooseVisual", &retrace::ignore},
331     //{"glXCopyContext", &retrace_glXCopyContext},
332     //{"glXCopyImageSubDataNV", &retrace_glXCopyImageSubDataNV},
333     {"glXCopySubBufferMESA", &retrace_glXCopySubBufferMESA},
334     {"glXCreateContextAttribsARB", &retrace_glXCreateContextAttribsARB},
335     {"glXCreateContext", &retrace_glXCreateContext},
336     //{"glXCreateContextWithConfigSGIX", &retrace_glXCreateContextWithConfigSGIX},
337     //{"glXCreateGLXPbufferSGIX", &retrace_glXCreateGLXPbufferSGIX},
338     //{"glXCreateGLXPixmap", &retrace_glXCreateGLXPixmap},
339     //{"glXCreateGLXPixmapWithConfigSGIX", &retrace_glXCreateGLXPixmapWithConfigSGIX},
340     {"glXCreateNewContext", &retrace_glXCreateNewContext},
341     {"glXCreatePbuffer", &retrace_glXCreatePbuffer},
342     {"glXCreatePixmap", &retrace_glXCreatePixmap},
343     {"XCreatePixmap", &retrace_XCreatePixmap},
344     {"XFreePixmap", &retrace_XFreePixmap},
345     {"PutImageData", &retrace_PutImageData},
346     {"glXCreateWindow", &retrace_glXCreateWindow},
347     //{"glXCushionSGI", &retrace_glXCushionSGI},
348     {"glXDestroyContext", &retrace_glXDestroyContext},
349     //{"glXDestroyGLXPbufferSGIX", &retrace_glXDestroyGLXPbufferSGIX},
350     //{"glXDestroyGLXPixmap", &retrace_glXDestroyGLXPixmap},
351     {"glXDestroyPbuffer", &retrace_glXDestroyPbuffer},
352     //{"glXDestroyPixmap", &retrace_glXDestroyPixmap},
353     {"glXDestroyWindow", &retrace_glXDestroyWindow},
354     //{"glXFreeContextEXT", &retrace_glXFreeContextEXT},
355     {"glXGetAGPOffsetMESA", &retrace::ignore},
356     {"glXGetClientString", &retrace::ignore},
357     {"glXGetConfig", &retrace::ignore},
358     {"glXGetContextIDEXT", &retrace::ignore},
359     {"glXGetCurrentContext", &retrace::ignore},
360     {"glXGetCurrentDisplayEXT", &retrace::ignore},
361     {"glXGetCurrentDisplay", &retrace::ignore},
362     {"glXGetCurrentDrawable", &retrace::ignore},
363     {"glXGetCurrentReadDrawable", &retrace::ignore},
364     {"glXGetCurrentReadDrawableSGI", &retrace::ignore},
365     {"glXGetFBConfigAttrib", &retrace_glXGetFBConfigAttrib},
366     {"glXGetFBConfigAttribSGIX", &retrace::ignore},
367     {"glXGetFBConfigFromVisualSGIX", &retrace::ignore},
368     {"glXGetFBConfigs", &retrace::ignore},
369     {"glXGetMscRateOML", &retrace::ignore},
370     {"glXGetProcAddressARB", &retrace::ignore},
371     {"glXGetProcAddress", &retrace::ignore},
372     {"glXGetSelectedEvent", &retrace::ignore},
373     {"glXGetSelectedEventSGIX", &retrace::ignore},
374     {"glXGetSwapIntervalMESA", &retrace::ignore},
375     {"glXGetSyncValuesOML", &retrace::ignore},
376     {"glXGetVideoSyncSGI", &retrace::ignore},
377     {"glXGetVisualFromFBConfig", &retrace::ignore},
378     {"glXGetVisualFromFBConfigSGIX", &retrace::ignore},
379     //{"glXImportContextEXT", &retrace_glXImportContextEXT},
380     {"glXIsDirect", &retrace::ignore},
381     //{"glXJoinSwapGroupNV", &retrace_glXJoinSwapGroupNV},
382     //{"glXJoinSwapGroupSGIX", &retrace_glXJoinSwapGroupSGIX},
383     {"glXMakeContextCurrent", &retrace_glXMakeContextCurrent},
384     //{"glXMakeCurrentReadSGI", &retrace_glXMakeCurrentReadSGI},
385     {"glXMakeCurrent", &retrace_glXMakeCurrent},
386     {"glXQueryChannelDeltasSGIX", &retrace::ignore},
387     {"glXQueryChannelRectSGIX", &retrace::ignore},
388     {"glXQueryContextInfoEXT", &retrace::ignore},
389     {"glXQueryContext", &retrace::ignore},
390     {"glXQueryDrawable", &retrace::ignore},
391     {"glXQueryExtension", &retrace::ignore},
392     {"glXQueryExtensionsString", &retrace::ignore},
393     {"glXQueryFrameCountNV", &retrace::ignore},
394     {"glXQueryGLXPbufferSGIX", &retrace::ignore},
395     {"glXQueryMaxSwapBarriersSGIX", &retrace::ignore},
396     {"glXQueryMaxSwapGroupsNV", &retrace::ignore},
397     {"glXQueryServerString", &retrace::ignore},
398     {"glXQuerySwapGroupNV", &retrace::ignore},
399     {"glXQueryVersion", &retrace::ignore},
400     //{"glXReleaseBuffersMESA", &retrace_glXReleaseBuffersMESA},
401     {"glXReleaseTexImageEXT", &retrace_glXReleaseTexImageEXT},
402     //{"glXResetFrameCountNV", &retrace_glXResetFrameCountNV},
403     {"glXSelectEvent", &retrace::ignore},
404     //{"glXSelectEventSGIX", &retrace_glXSelectEventSGIX},
405     //{"glXSet3DfxModeMESA", &retrace_glXSet3DfxModeMESA},
406     //{"glXSwapBuffersMscOML", &retrace_glXSwapBuffersMscOML},
407     {"glXSwapBuffers", &retrace_glXSwapBuffers},
408     {"glXSwapIntervalEXT", &retrace::ignore},
409     {"glXSwapIntervalSGI", &retrace::ignore},
410     //{"glXUseXFont", &retrace_glXUseXFont},
411     {"glXWaitForMscOML", &retrace::ignore},
412     {"glXWaitForSbcOML", &retrace::ignore},
413     {"glXWaitGL", &retrace::ignore},
414     {"glXWaitVideoSyncSGI", &retrace::ignore},
415     {"glXWaitX", &retrace::ignore},
416     {NULL, NULL},
417 };
418