1/*
2* Copyright (C) 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#ifndef __COMMON_HOST_CONNECTION_H
17#define __COMMON_HOST_CONNECTION_H
18
19#include "IOStream.h"
20#include "renderControl_enc.h"
21#include "ChecksumCalculator.h"
22#include "goldfish_dma.h"
23
24#include <string>
25
26class GLEncoder;
27struct gl_client_context_t;
28class GL2Encoder;
29struct gl2_client_context_t;
30
31// SyncImpl determines the presence of host/guest OpenGL fence sync
32// capabilities. It corresponds exactly to EGL_ANDROID_native_fence_sync
33// capability, but for the emulator, we need to make sure that
34// OpenGL pipe protocols match, so we use a special extension name
35// here.
36// SYNC_IMPL_NONE means that the native fence sync capability is
37// not present, and we will end up using the equivalent of glFinish
38// in order to preserve buffer swapping order.
39// SYNC_IMPL_NATIVE_SYNC means that we do have native fence sync
40// capability, and we will use a fence fd to synchronize buffer swaps.
41enum SyncImpl {
42    SYNC_IMPL_NONE = 0,
43    SYNC_IMPL_NATIVE_SYNC_V2 = 1,
44    SYNC_IMPL_NATIVE_SYNC_V3 = 2,
45};
46
47// Interface:
48// Use the highest of v2 or v3 that show up, making us
49// SYNC_IMPL_NATIVE_SYNC_V2 or SYNC_IMPL_NATIVE_SYNC_V3.
50static const char kRCNativeSyncV2[] = "ANDROID_EMU_native_sync_v2";
51static const char kRCNativeSyncV3[] = "ANDROID_EMU_native_sync_v3";
52
53// DMA for OpenGL
54enum DmaImpl {
55    DMA_IMPL_NONE = 0,
56    DMA_IMPL_v1 = 1,
57};
58
59static const char kDmaExtStr_v1[] = "ANDROID_EMU_dma_v1";
60
61// OpenGL ES max supported version
62enum GLESMaxVersion {
63    GLES_MAX_VERSION_2 = 0,
64    GLES_MAX_VERSION_3_0 = 1,
65    GLES_MAX_VERSION_3_1 = 2,
66    GLES_MAX_VERSION_3_2 = 3,
67};
68
69static const char kGLESMaxVersion_2[] = "ANDROID_EMU_gles_max_version_2";
70static const char kGLESMaxVersion_3_0[] = "ANDROID_EMU_gles_max_version_3_0";
71static const char kGLESMaxVersion_3_1[] = "ANDROID_EMU_gles_max_version_3_1";
72static const char kGLESMaxVersion_3_2[] = "ANDROID_EMU_gles_max_version_3_2";
73
74// No querying errors from host extension
75static const char kGLESNoHostError[] = "ANDROID_EMU_gles_no_host_error";
76
77// ExtendedRCEncoderContext is an extended version of renderControl_encoder_context_t
78// that will be used to track SyncImpl.
79class ExtendedRCEncoderContext : public renderControl_encoder_context_t {
80public:
81    ExtendedRCEncoderContext(IOStream *stream, ChecksumCalculator *checksumCalculator)
82        : renderControl_encoder_context_t(stream, checksumCalculator) {
83        m_dmaCxt = NULL;
84        }
85    void setSyncImpl(SyncImpl syncImpl) { m_syncImpl = syncImpl; }
86    void setDmaImpl(DmaImpl dmaImpl) { m_dmaImpl = dmaImpl; }
87    bool hasNativeSync() const { return m_syncImpl >= SYNC_IMPL_NATIVE_SYNC_V2; }
88    bool hasNativeSyncV3() const { return m_syncImpl >= SYNC_IMPL_NATIVE_SYNC_V3; }
89    DmaImpl getDmaVersion() const { return m_dmaImpl; }
90    void bindDmaContext(struct goldfish_dma_context* cxt) { m_dmaCxt = cxt; }
91    virtual uint64_t lockAndWriteDma(void* data, uint32_t size) {
92        ALOGV("%s: call", __FUNCTION__);
93        if (!m_dmaCxt) {
94            ALOGE("%s: ERROR: No DMA context bound!",
95                  __FUNCTION__);
96            return 0;
97        }
98        goldfish_dma_lock(m_dmaCxt);
99        goldfish_dma_write(m_dmaCxt, data, size);
100        uint64_t paddr = goldfish_dma_guest_paddr(m_dmaCxt);
101        ALOGV("%s: paddr=0x%llx", __FUNCTION__, paddr);
102        return paddr;
103    }
104    void setGLESMaxVersion(GLESMaxVersion ver) { m_glesMaxVersion = ver; }
105    GLESMaxVersion getGLESMaxVersion() const { return m_glesMaxVersion; }
106private:
107    SyncImpl m_syncImpl;
108    DmaImpl m_dmaImpl;
109    struct goldfish_dma_context* m_dmaCxt;
110    GLESMaxVersion m_glesMaxVersion;
111};
112
113struct EGLThreadInfo;
114
115class HostConnection
116{
117public:
118    static HostConnection *get();
119    static HostConnection *getWithThreadInfo(EGLThreadInfo* tInfo);
120    static void exit();
121    ~HostConnection();
122
123    GLEncoder *glEncoder();
124    GL2Encoder *gl2Encoder();
125    ExtendedRCEncoderContext *rcEncoder();
126    ChecksumCalculator *checksumHelper() { return &m_checksumHelper; }
127
128    void flush() {
129        if (m_stream) {
130            m_stream->flush();
131        }
132    }
133
134    void setGrallocOnly(bool gralloc_only) {
135        m_grallocOnly = gralloc_only;
136    }
137
138    bool isGrallocOnly() const { return m_grallocOnly; }
139
140    int getPipeFd() const { return m_pipeFd; }
141
142private:
143    HostConnection();
144    static gl_client_context_t  *s_getGLContext();
145    static gl2_client_context_t *s_getGL2Context();
146
147    const std::string& queryGLExtensions(ExtendedRCEncoderContext *rcEnc);
148    // setProtocol initilizes GL communication protocol for checksums
149    // should be called when m_rcEnc is created
150    void setChecksumHelper(ExtendedRCEncoderContext *rcEnc);
151    void queryAndSetSyncImpl(ExtendedRCEncoderContext *rcEnc);
152    void queryAndSetDmaImpl(ExtendedRCEncoderContext *rcEnc);
153    void queryAndSetGLESMaxVersion(ExtendedRCEncoderContext *rcEnc);
154    void queryAndSetNoErrorState(ExtendedRCEncoderContext *rcEnc);
155
156private:
157    IOStream *m_stream;
158    GLEncoder   *m_glEnc;
159    GL2Encoder  *m_gl2Enc;
160    ExtendedRCEncoderContext *m_rcEnc;
161    ChecksumCalculator m_checksumHelper;
162    std::string m_glExtensions;
163    bool m_grallocOnly;
164    int m_pipeFd;
165    bool m_noHostError;
166};
167
168#endif
169