gltrace_context.cpp revision f132ac35d82a2960542619fb3fb91d22ab256dc7
1/*
2 * Copyright 2011, The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include <pthread.h>
18
19extern "C" {
20#include "liblzf/lzf.h"
21}
22
23#include "gltrace_context.h"
24
25namespace android {
26namespace gltrace {
27
28using ::android::gl_hooks_t;
29
30static pthread_key_t sTLSKey = -1;
31static pthread_once_t sPthreadOnceKey = PTHREAD_ONCE_INIT;
32
33void createTLSKey() {
34    pthread_key_create(&sTLSKey, NULL);
35}
36
37GLTraceContext *getGLTraceContext() {
38    return (GLTraceContext*) pthread_getspecific(sTLSKey);
39}
40
41void setGLTraceContext(GLTraceContext *c) {
42    pthread_setspecific(sTLSKey, c);
43}
44
45void initContext(unsigned version, gl_hooks_t *hooks) {
46    pthread_once(&sPthreadOnceKey, createTLSKey);
47
48    GLTraceContext *context = new GLTraceContext();
49    context->hooks = hooks;
50
51    setGLTraceContext(context);
52}
53
54void releaseContext() {
55    GLTraceContext *c = getGLTraceContext();
56    if (c != NULL) {
57        delete c;
58        setGLTraceContext(NULL);
59    }
60}
61
62GLTraceContext::GLTraceContext() {
63    fbcontents = fbcompressed = NULL;
64    fbcontentsSize = 0;
65}
66
67void GLTraceContext::resizeFBMemory(unsigned minSize) {
68    if (fbcontentsSize >= minSize) {
69        return;
70    }
71
72    if (fbcontents != NULL) {
73        free(fbcontents);
74        free(fbcompressed);
75    }
76
77    fbcontents = malloc(minSize);
78    fbcompressed = malloc(minSize);
79
80    fbcontentsSize = minSize;
81}
82
83/** obtain a pointer to the compressed framebuffer image */
84void GLTraceContext::getCompressedFB(void **fb, unsigned *fbsize, unsigned *fbwidth,
85                            unsigned *fbheight, FBBinding fbToRead) {
86    int viewport[4] = {};
87    hooks->gl.glGetIntegerv(GL_VIEWPORT, viewport);
88    unsigned fbContentsSize = viewport[2] * viewport[3] * 4;
89
90    resizeFBMemory(fbContentsSize);
91
92    // switch current framebuffer binding if necessary
93    GLint currentFb = -1;
94    bool fbSwitched = false;
95    if (fbToRead != CURRENTLY_BOUND_FB) {
96        hooks->gl.glGetIntegerv(GL_FRAMEBUFFER_BINDING, &currentFb);
97
98        if (currentFb != 0) {
99            hooks->gl.glBindFramebuffer(GL_FRAMEBUFFER, 0);
100            fbSwitched = true;
101        }
102    }
103
104    hooks->gl.glReadPixels(viewport[0], viewport[1], viewport[2], viewport[3],
105                                        GL_RGBA, GL_UNSIGNED_BYTE, fbcontents);
106
107    // switch back to previously bound buffer if necessary
108    if (fbSwitched) {
109        hooks->gl.glBindFramebuffer(GL_FRAMEBUFFER, currentFb);
110    }
111
112    *fbsize = lzf_compress(fbcontents, fbContentsSize, fbcompressed, fbContentsSize);
113    *fb = fbcompressed;
114    *fbwidth = viewport[2];
115    *fbheight = viewport[3];
116}
117
118}; // namespace gltrace
119}; // namespace android
120