Remove the member "secure" from overlay_buf_info. This member was used to indicate secure content and this info was later extracted out into existing flags. Now we use the same flags, right from hwc to mark secure content. The member above had junk value, since it wasnt initialized. This caused, normal videos to fail with IOMMU. Removal of the member and marking the existing flags fixes this. Change-Id: Ib5a2439fde7114c20e478fbee5e4d276680c316a
499 lines
17 KiB
C++
499 lines
17 KiB
C++
/*
|
|
* Copyright (c) 2012, Code Aurora Forum. All rights reserved.
|
|
|
|
* Redistribution and use in source and binary forms, with or without
|
|
* modification, are permitted provided that the following conditions are
|
|
* met:
|
|
* * Redistributions of source code must retain the above copyright
|
|
* notice, this list of conditions and the following disclaimer.
|
|
* * Redistributions in binary form must reproduce the above
|
|
* copyright notice, this list of conditions and the following
|
|
* disclaimer in the documentation and/or other materials provided
|
|
* with the distribution.
|
|
* * Neither the name of Code Aurora Forum, Inc. nor the names of its
|
|
* contributors may be used to endorse or promote products derived
|
|
* from this software without specific prior written permission.
|
|
*
|
|
* THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
|
|
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
|
|
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
|
|
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
|
|
* BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
|
|
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
|
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
|
|
* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
|
|
* WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
|
|
* OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
|
|
* IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
|
|
*/
|
|
|
|
#define EXTDEBUG 0
|
|
class ExtDispOnly {
|
|
|
|
enum ExternalOnlyMode {
|
|
EXT_ONLY_MODE_OFF = 0,
|
|
EXT_ONLY_MODE_ON = 1,
|
|
};
|
|
|
|
enum {
|
|
MAX_EXT_ONLY_LAYERS = 2,
|
|
};
|
|
|
|
public:
|
|
/* Initialize, allocate data members */
|
|
static void init();
|
|
|
|
/* Deallocate data members */
|
|
static void destroy();
|
|
|
|
/* Closes all the overlay channels */
|
|
static void close();
|
|
|
|
/* Prepare overlay and configures mdp pipes */
|
|
static int prepare(hwc_context_t *ctx, hwc_layer_t *layer, int index,
|
|
bool waitForVsync);
|
|
|
|
/* Returns status of external-only mode */
|
|
static bool isModeOn();
|
|
|
|
/* Updates stats and pipe config related to external_only and external_block layers
|
|
* If we are staring or stopping this mode, update default mirroring.
|
|
*/
|
|
static int update(hwc_context_t* ctx, hwc_layer_list_t* list);
|
|
|
|
/* Stores the locked handle for the buffer that was successfully queued */
|
|
static void storeLockedHandles(hwc_layer_list_t* list);
|
|
|
|
/* Queue buffers to mdp for display */
|
|
static int draw(hwc_context_t *ctx, hwc_layer_list_t *list);
|
|
|
|
private:
|
|
/* Locks a buffer and marks it as locked */
|
|
static void lockBuffer(native_handle_t *hnd);
|
|
|
|
/* Unlocks a buffer and clears the locked flag */
|
|
static void unlockBuffer(native_handle_t *hnd);
|
|
|
|
/* Unlocks buffers queued in previous round (and displayed by now)
|
|
* Clears the handle cache.
|
|
*/
|
|
static void unlockPreviousBuffers();
|
|
|
|
/* Closes the a range of overlay channels */
|
|
static void closeRange(int start);
|
|
|
|
/* Start default external mirroring */
|
|
static void startDefaultMirror(hwc_context_t* ctx);
|
|
|
|
/* Stop default external mirroring */
|
|
static void stopDefaultMirror(hwc_context_t* ctx);
|
|
|
|
/* Checks if external-only mode is starting */
|
|
static bool isExtModeStarting(hwc_context_t* ctx, const int&
|
|
numExtLayers);
|
|
|
|
/* Checks if external-only mode is stopping */
|
|
static bool isExtModeStopping(hwc_context_t* ctx, const int&
|
|
numExtLayers);
|
|
|
|
//Data members
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
static overlay::OverlayUI* sOvExtUI[MAX_EXT_ONLY_LAYERS];
|
|
static native_handle_t* sPreviousExtHandle[MAX_EXT_ONLY_LAYERS];
|
|
static ExternalOnlyMode sExtOnlyMode;
|
|
static int sNumExtOnlyLayers;
|
|
static bool sSkipLayerPresent;
|
|
static bool sBlockLayerPresent;
|
|
static int sBlockLayerIndex;
|
|
#endif
|
|
}; //class ExtDispOnly
|
|
|
|
void ExtDispOnly::lockBuffer(native_handle_t *hnd) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
private_handle_t* phnd = (private_handle_t*)hnd;
|
|
|
|
//Genlock is reference counted and recursive.
|
|
//Do not accidently lock a locked buffer.
|
|
if(phnd && (phnd->flags & private_handle_t::PRIV_FLAGS_HWC_LOCK)) {
|
|
LOGE_IF(EXTDEBUG, "%s: handle %p already locked", __func__, phnd);
|
|
return;
|
|
}
|
|
if (GENLOCK_FAILURE == genlock_lock_buffer(hnd, GENLOCK_READ_LOCK,
|
|
GENLOCK_MAX_TIMEOUT)) {
|
|
LOGE("%s: genlock_lock_buffer(READ) failed", __func__);
|
|
return;
|
|
}
|
|
phnd->flags |= private_handle_t::PRIV_FLAGS_HWC_LOCK;
|
|
LOGE_IF(EXTDEBUG, "%s: locked handle = %p", __func__, hnd);
|
|
#endif
|
|
}
|
|
|
|
void ExtDispOnly::unlockBuffer(native_handle_t *hnd) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
//Check if buffer is still around
|
|
if(private_handle_t::validate(hnd) != 0) {
|
|
LOGE("%s Handle already deallocated", __func__);
|
|
return;
|
|
}
|
|
|
|
private_handle_t* phnd = (private_handle_t*)hnd;
|
|
|
|
//Check if buffer was locked in the first place
|
|
if((phnd->flags & private_handle_t::PRIV_FLAGS_HWC_LOCK) == 0) {
|
|
LOGE("%s Handle not locked, cannot unlock", __func__);
|
|
return;
|
|
}
|
|
|
|
//Actually try to unlock
|
|
if (GENLOCK_FAILURE == genlock_unlock_buffer(hnd)) {
|
|
LOGE("%s: genlock_unlock_buffer failed", __func__);
|
|
return;
|
|
}
|
|
|
|
//Clear the locked flag
|
|
phnd->flags &= ~private_handle_t::PRIV_FLAGS_HWC_LOCK;
|
|
LOGE_IF(EXTDEBUG, "%s: unlocked handle = %p", __func__, hnd);
|
|
#endif
|
|
}
|
|
|
|
void ExtDispOnly::unlockPreviousBuffers() {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
for(int i = 0; (i < MAX_EXT_ONLY_LAYERS) && sPreviousExtHandle[i]; i++) {
|
|
LOGE_IF(EXTDEBUG, "%s", __func__);
|
|
ExtDispOnly::unlockBuffer(sPreviousExtHandle[i]);
|
|
sPreviousExtHandle[i] = NULL;
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ExtDispOnly::init() {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
for(int i = 0; i < MAX_EXT_ONLY_LAYERS; i++) {
|
|
sOvExtUI[i] = new overlay::OverlayUI();
|
|
sPreviousExtHandle[i] = NULL;
|
|
}
|
|
sExtOnlyMode = EXT_ONLY_MODE_OFF;
|
|
sNumExtOnlyLayers = 0;
|
|
sSkipLayerPresent = false;
|
|
sBlockLayerPresent = false;
|
|
sBlockLayerIndex = -1;
|
|
LOGE_IF(EXTDEBUG, "%s", __func__);
|
|
#endif
|
|
}
|
|
|
|
void ExtDispOnly::destroy() {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
for(int i = 0; i < MAX_EXT_ONLY_LAYERS; i++) {
|
|
delete sOvExtUI[i];
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void ExtDispOnly::closeRange(int start) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
for (int index = start; index < MAX_EXT_ONLY_LAYERS; index++) {
|
|
if(sPreviousExtHandle[index]) {
|
|
LOGE_IF(EXTDEBUG, "%s", __func__);
|
|
ExtDispOnly::unlockBuffer(sPreviousExtHandle[index]);
|
|
sPreviousExtHandle[index] = NULL;
|
|
}
|
|
sOvExtUI[index]->closeChannel();
|
|
}
|
|
#endif
|
|
}
|
|
|
|
void inline ExtDispOnly::close() {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
closeRange(0);
|
|
#endif
|
|
}
|
|
|
|
int ExtDispOnly::prepare(hwc_context_t *ctx, hwc_layer_t *layer, int index,
|
|
bool waitForVsync) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
if(ctx->mHDMIEnabled == EXT_TYPE_NONE ||
|
|
ctx->pendingHDMI == true)
|
|
return -1;
|
|
|
|
if (ctx && sOvExtUI[index]) {
|
|
private_hwc_module_t* hwcModule = reinterpret_cast<
|
|
private_hwc_module_t*>(ctx->device.common.module);
|
|
if (!hwcModule) {
|
|
LOGE("%s null module", __func__);
|
|
return -1;
|
|
}
|
|
private_handle_t *hnd = (private_handle_t *)layer->handle;
|
|
if(!hnd) {
|
|
LOGE("%s handle null", __func__);
|
|
return -1;
|
|
}
|
|
overlay::OverlayUI *ovUI = sOvExtUI[index];
|
|
int ret = 0;
|
|
//int orientation = layer->transform;
|
|
//Assuming layers will always be source landscape
|
|
const int orientation = 0;
|
|
overlay_buffer_info info;
|
|
hwc_rect_t sourceCrop = layer->sourceCrop;
|
|
info.width = sourceCrop.right - sourceCrop.left;
|
|
info.height = sourceCrop.bottom - sourceCrop.top;
|
|
info.format = hnd->format;
|
|
info.size = hnd->size;
|
|
|
|
|
|
const int fbnum = ctx->mHDMIEnabled; //HDMI or WFD
|
|
const bool isFg = false;
|
|
//Just to differentiate zorders for different layers
|
|
const int zorder = index;
|
|
const bool isVGPipe = true;
|
|
ovUI->setSource(info, orientation);
|
|
ovUI->setDisplayParams(fbnum, waitForVsync, isFg, zorder, isVGPipe);
|
|
const int fbWidth = ovUI->getFBWidth();
|
|
const int fbHeight = ovUI->getFBHeight();
|
|
ovUI->setPosition(0, 0, fbWidth, fbHeight);
|
|
if(ovUI->commit() != overlay::NO_ERROR) {
|
|
LOGE("%s: Overlay Commit failed", __func__);
|
|
return -1;
|
|
}
|
|
}
|
|
LOGE_IF(EXTDEBUG, "%s", __func__);
|
|
#endif
|
|
return overlay::NO_ERROR;
|
|
}
|
|
|
|
inline void ExtDispOnly::startDefaultMirror(hwc_context_t* ctx) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
hwc_composer_device_t* dev = (hwc_composer_device_t*) ctx;
|
|
private_hwc_module_t* hwcModule =
|
|
reinterpret_cast<private_hwc_module_t*>(dev->common.module);
|
|
framebuffer_device_t *fbDev = hwcModule->fbDevice;
|
|
if (fbDev) {
|
|
//mHDMIEnabled could be HDMI/WFD/NO EXTERNAL
|
|
fbDev->enableHDMIOutput(fbDev, ctx->mHDMIEnabled);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
inline void ExtDispOnly::stopDefaultMirror(hwc_context_t* ctx) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
hwc_composer_device_t* dev = (hwc_composer_device_t*) ctx;
|
|
private_hwc_module_t* hwcModule =
|
|
reinterpret_cast<private_hwc_module_t*>(dev->common.module);
|
|
framebuffer_device_t *fbDev = hwcModule->fbDevice;
|
|
if (fbDev) {
|
|
fbDev->enableHDMIOutput(fbDev, EXT_TYPE_NONE);
|
|
}
|
|
#endif
|
|
}
|
|
|
|
inline bool ExtDispOnly::isExtModeStarting(hwc_context_t* ctx, const int&
|
|
numExtLayers) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
return ((sExtOnlyMode == EXT_ONLY_MODE_OFF) && numExtLayers);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
inline bool ExtDispOnly::isExtModeStopping(hwc_context_t* ctx, const int&
|
|
numExtLayers) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
return ((sExtOnlyMode == EXT_ONLY_MODE_ON) && (numExtLayers == 0));
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
inline bool ExtDispOnly::isModeOn() {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
return (sExtOnlyMode == EXT_ONLY_MODE_ON);
|
|
#endif
|
|
return false;
|
|
}
|
|
|
|
int ExtDispOnly::update(hwc_context_t* ctx, hwc_layer_list_t* list) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
int aNumExtLayers = 0;
|
|
bool aSkipLayerPresent = false;
|
|
bool aBlockLayerPresent = false;
|
|
int aBlockLayerIndex = -1;
|
|
|
|
//Book-keeping done each cycle
|
|
for (size_t i = 0; i < list->numHwLayers; i++) {
|
|
private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
|
|
// Dont draw in this round
|
|
if(list->hwLayers[i].flags & HWC_SKIP_LAYER) {
|
|
aSkipLayerPresent = true;
|
|
}
|
|
if(hnd && (hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY)) {
|
|
aNumExtLayers++;
|
|
// No way we can let this be drawn by GPU to fb0
|
|
if(list->hwLayers[i].flags & HWC_SKIP_LAYER) {
|
|
list->hwLayers[i].flags &= ~ HWC_SKIP_LAYER;
|
|
}
|
|
list->hwLayers[i].flags |= HWC_USE_EXT_ONLY;
|
|
list->hwLayers[i].compositionType = HWC_USE_OVERLAY;
|
|
list->hwLayers[i].hints &= ~HWC_HINT_CLEAR_FB;
|
|
//EXTERNAL_BLOCK is always an add-on
|
|
if(hnd && (hnd->flags &
|
|
private_handle_t::PRIV_FLAGS_EXTERNAL_BLOCK)) {
|
|
aBlockLayerPresent = true;
|
|
aBlockLayerIndex = i;
|
|
list->hwLayers[i].flags |= HWC_USE_EXT_BLOCK;
|
|
}
|
|
}
|
|
}
|
|
|
|
//Update Default mirroring state
|
|
if (isExtModeStarting(ctx, aNumExtLayers)) {
|
|
stopDefaultMirror(ctx);
|
|
} else if (isExtModeStopping(ctx, aNumExtLayers)) {
|
|
startDefaultMirror(ctx);
|
|
}
|
|
|
|
//Cache our stats
|
|
sExtOnlyMode = aNumExtLayers ? EXT_ONLY_MODE_ON : EXT_ONLY_MODE_OFF;
|
|
sNumExtOnlyLayers = aNumExtLayers;
|
|
sSkipLayerPresent = aSkipLayerPresent;
|
|
sBlockLayerPresent = aBlockLayerPresent;
|
|
sBlockLayerIndex = aBlockLayerIndex;
|
|
|
|
LOGE_IF(EXTDEBUG, "%s: numExtLayers = %d skipLayerPresent = %d", __func__,
|
|
aNumExtLayers, aSkipLayerPresent);
|
|
//If skip layer present return. Buffers to be unlocked in draw phase.
|
|
if(aSkipLayerPresent) {
|
|
return overlay::NO_ERROR;
|
|
}
|
|
|
|
//If External is not connected, dont setup pipes, just return
|
|
if(ctx->mHDMIEnabled == EXT_TYPE_NONE ||
|
|
ctx->pendingHDMI == true) {
|
|
ExtDispOnly::close();
|
|
return -1;
|
|
}
|
|
|
|
|
|
//Update pipes
|
|
bool waitForVsync = true;
|
|
bool index = 0;
|
|
|
|
if (aBlockLayerPresent) {
|
|
ExtDispOnly::closeRange(1);
|
|
ExtDispOnly::prepare(ctx, &(list->hwLayers[aBlockLayerIndex]),
|
|
index, waitForVsync);
|
|
} else if (aNumExtLayers) {
|
|
ExtDispOnly::closeRange(aNumExtLayers);
|
|
for (size_t i = 0; i < list->numHwLayers; i++) {
|
|
private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
|
|
if(hnd && hnd->flags & private_handle_t::PRIV_FLAGS_EXTERNAL_ONLY) {
|
|
waitForVsync = (index == (aNumExtLayers - 1));
|
|
ExtDispOnly::prepare(ctx, &(list->hwLayers[i]),
|
|
index, waitForVsync);
|
|
index++;
|
|
}
|
|
}
|
|
} else {
|
|
ExtDispOnly::close();
|
|
}
|
|
#endif
|
|
return overlay::NO_ERROR;
|
|
}
|
|
|
|
void ExtDispOnly::storeLockedHandles(hwc_layer_list_t* list) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
int index = 0;
|
|
if(sBlockLayerPresent) {
|
|
private_handle_t *hnd = (private_handle_t *)
|
|
list->hwLayers[sBlockLayerIndex].handle;
|
|
if(list->hwLayers[sBlockLayerIndex].flags & HWC_USE_EXT_ONLY) {
|
|
if(!(hnd->flags & private_handle_t::PRIV_FLAGS_HWC_LOCK)) {
|
|
ExtDispOnly::lockBuffer(hnd);
|
|
}
|
|
sPreviousExtHandle[index] = hnd;
|
|
LOGE_IF(EXTDEBUG, "%s BLOCK: handle = %p", __func__, hnd);
|
|
return;
|
|
}
|
|
}
|
|
for(int i = 0; i < list->numHwLayers; i++) {
|
|
private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
|
|
if(list->hwLayers[i].flags & HWC_USE_EXT_ONLY) {
|
|
if(!(hnd->flags & private_handle_t::PRIV_FLAGS_HWC_LOCK)) {
|
|
ExtDispOnly::lockBuffer(hnd);
|
|
}
|
|
sPreviousExtHandle[index] = hnd;
|
|
index++;
|
|
LOGE_IF(EXTDEBUG, "%s: handle = %p", __func__, hnd);
|
|
}
|
|
}
|
|
#endif
|
|
}
|
|
|
|
int ExtDispOnly::draw(hwc_context_t *ctx, hwc_layer_list_t *list) {
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
LOGE_IF(EXTDEBUG, "%s", __func__);
|
|
if(ctx->mHDMIEnabled == EXT_TYPE_NONE||
|
|
ctx->pendingHDMI == true) {
|
|
ExtDispOnly::close();
|
|
return -1;
|
|
}
|
|
|
|
int ret = overlay::NO_ERROR;
|
|
int index = 0;
|
|
|
|
//If skip layer present or list invalid unlock and return.
|
|
if(sSkipLayerPresent || list == NULL) {
|
|
ExtDispOnly::unlockPreviousBuffers();
|
|
return overlay::NO_ERROR;
|
|
}
|
|
|
|
if(sBlockLayerPresent) {
|
|
private_handle_t *hnd = (private_handle_t*)
|
|
list->hwLayers[sBlockLayerIndex].handle;
|
|
ExtDispOnly::lockBuffer(hnd);
|
|
ret = sOvExtUI[index]->queueBuffer(hnd);
|
|
if (ret) {
|
|
LOGE("%s queueBuffer failed", __func__);
|
|
// Unlock the locked buffer
|
|
ExtDispOnly::unlockBuffer(hnd);
|
|
ExtDispOnly::close();
|
|
return -1;
|
|
}
|
|
ExtDispOnly::unlockPreviousBuffers();
|
|
ExtDispOnly::storeLockedHandles(list);
|
|
return overlay::NO_ERROR;
|
|
}
|
|
|
|
for(int i = 0; i < list->numHwLayers; i++) {
|
|
private_handle_t *hnd = (private_handle_t *)list->hwLayers[i].handle;
|
|
if(hnd && list->hwLayers[i].flags & HWC_USE_EXT_ONLY) {
|
|
overlay::OverlayUI *ovUI = sOvExtUI[index];
|
|
ExtDispOnly::lockBuffer(hnd);
|
|
ret = ovUI->queueBuffer(hnd);
|
|
if (ret) {
|
|
LOGE("%s queueBuffer failed", __func__);
|
|
// Unlock the all the currently locked buffers
|
|
for (int j = 0; j <= i; j++) {
|
|
private_handle_t *tmphnd =
|
|
(private_handle_t *)list->hwLayers[j].handle;
|
|
if(hnd && list->hwLayers[j].flags & HWC_USE_EXT_ONLY)
|
|
ExtDispOnly::unlockBuffer(tmphnd);
|
|
}
|
|
ExtDispOnly::close();
|
|
return -1;
|
|
}
|
|
index++;
|
|
}
|
|
}
|
|
ExtDispOnly::unlockPreviousBuffers();
|
|
ExtDispOnly::storeLockedHandles(list);
|
|
#endif
|
|
return overlay::NO_ERROR;
|
|
}
|
|
|
|
#if defined (HDMI_DUAL_DISPLAY) && defined (USE_OVERLAY)
|
|
overlay::OverlayUI* ExtDispOnly::sOvExtUI[MAX_EXT_ONLY_LAYERS];
|
|
native_handle_t* ExtDispOnly::sPreviousExtHandle[MAX_EXT_ONLY_LAYERS];
|
|
ExtDispOnly::ExternalOnlyMode ExtDispOnly::sExtOnlyMode;
|
|
int ExtDispOnly::sNumExtOnlyLayers;
|
|
bool ExtDispOnly::sSkipLayerPresent;
|
|
bool ExtDispOnly::sBlockLayerPresent;
|
|
int ExtDispOnly::sBlockLayerIndex;
|
|
#endif
|