1441e847feb0e055ecb004802802cea07782ab228Andy McFadden/* 2441e847feb0e055ecb004802802cea07782ab228Andy McFadden * Copyright 2013 The Android Open Source Project 3441e847feb0e055ecb004802802cea07782ab228Andy McFadden * 4441e847feb0e055ecb004802802cea07782ab228Andy McFadden * Licensed under the Apache License, Version 2.0 (the "License"); 5441e847feb0e055ecb004802802cea07782ab228Andy McFadden * you may not use this file except in compliance with the License. 6441e847feb0e055ecb004802802cea07782ab228Andy McFadden * You may obtain a copy of the License at 7441e847feb0e055ecb004802802cea07782ab228Andy McFadden * 8441e847feb0e055ecb004802802cea07782ab228Andy McFadden * http://www.apache.org/licenses/LICENSE-2.0 9441e847feb0e055ecb004802802cea07782ab228Andy McFadden * 10441e847feb0e055ecb004802802cea07782ab228Andy McFadden * Unless required by applicable law or agreed to in writing, software 11441e847feb0e055ecb004802802cea07782ab228Andy McFadden * distributed under the License is distributed on an "AS IS" BASIS, 12441e847feb0e055ecb004802802cea07782ab228Andy McFadden * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13441e847feb0e055ecb004802802cea07782ab228Andy McFadden * See the License for the specific language governing permissions and 14441e847feb0e055ecb004802802cea07782ab228Andy McFadden * limitations under the License. 15441e847feb0e055ecb004802802cea07782ab228Andy McFadden */ 16441e847feb0e055ecb004802802cea07782ab228Andy McFadden 17884989c67081190ff864419328e9e81506db67caMark Salyzyn#include <assert.h> 18884989c67081190ff864419328e9e81506db67caMark Salyzyn#include <inttypes.h> 19884989c67081190ff864419328e9e81506db67caMark Salyzyn#include <stdlib.h> 20884989c67081190ff864419328e9e81506db67caMark Salyzyn 21441e847feb0e055ecb004802802cea07782ab228Andy McFadden#define LOG_TAG "ScreenRecord" 22441e847feb0e055ecb004802802cea07782ab228Andy McFadden//#define LOG_NDEBUG 0 23441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <utils/Log.h> 24441e847feb0e055ecb004802802cea07782ab228Andy McFadden 25441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <gui/BufferQueue.h> 26441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <gui/GraphicBufferAlloc.h> 27441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <gui/Surface.h> 28441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <cutils/properties.h> 29441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <utils/misc.h> 30441e847feb0e055ecb004802802cea07782ab228Andy McFadden 31441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <GLES2/gl2.h> 32441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include <GLES2/gl2ext.h> 33441e847feb0e055ecb004802802cea07782ab228Andy McFadden 34441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include "screenrecord.h" 35441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include "Overlay.h" 36441e847feb0e055ecb004802802cea07782ab228Andy McFadden#include "TextRenderer.h" 37441e847feb0e055ecb004802802cea07782ab228Andy McFadden 38441e847feb0e055ecb004802802cea07782ab228Andy McFaddenusing namespace android; 39441e847feb0e055ecb004802802cea07782ab228Andy McFadden 40441e847feb0e055ecb004802802cea07782ab228Andy McFadden// System properties to look up and display on the info screen. 41441e847feb0e055ecb004802802cea07782ab228Andy McFaddenconst char* Overlay::kPropertyNames[] = { 42441e847feb0e055ecb004802802cea07782ab228Andy McFadden "ro.build.description", 43441e847feb0e055ecb004802802cea07782ab228Andy McFadden // includes ro.build.id, ro.build.product, ro.build.tags, ro.build.type, 44441e847feb0e055ecb004802802cea07782ab228Andy McFadden // and ro.build.version.release 45441e847feb0e055ecb004802802cea07782ab228Andy McFadden "ro.product.manufacturer", 46441e847feb0e055ecb004802802cea07782ab228Andy McFadden "ro.product.model", 47441e847feb0e055ecb004802802cea07782ab228Andy McFadden "ro.board.platform", 48441e847feb0e055ecb004802802cea07782ab228Andy McFadden "ro.revision", 49441e847feb0e055ecb004802802cea07782ab228Andy McFadden "dalvik.vm.heapgrowthlimit", 50441e847feb0e055ecb004802802cea07782ab228Andy McFadden "dalvik.vm.heapsize", 51483f59ab9fb4b2d8ab212f77a50eed0528beca58Brian Carlstrom "persist.sys.dalvik.vm.lib.2", 52441e847feb0e055ecb004802802cea07782ab228Andy McFadden //"ro.product.cpu.abi", 53441e847feb0e055ecb004802802cea07782ab228Andy McFadden //"ro.bootloader", 54441e847feb0e055ecb004802802cea07782ab228Andy McFadden //"this-never-appears!", 55441e847feb0e055ecb004802802cea07782ab228Andy McFadden}; 56441e847feb0e055ecb004802802cea07782ab228Andy McFadden 57441e847feb0e055ecb004802802cea07782ab228Andy McFadden 58441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Overlay::start(const sp<IGraphicBufferProducer>& outputSurface, 59441e847feb0e055ecb004802802cea07782ab228Andy McFadden sp<IGraphicBufferProducer>* pBufferProducer) { 60441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGV("Overlay::start"); 61441e847feb0e055ecb004802802cea07782ab228Andy McFadden mOutputSurface = outputSurface; 62441e847feb0e055ecb004802802cea07782ab228Andy McFadden 63441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Grab the current monotonic time and the current wall-clock time so we 64441e847feb0e055ecb004802802cea07782ab228Andy McFadden // can map one to the other. This allows the overlay counter to advance 65441e847feb0e055ecb004802802cea07782ab228Andy McFadden // by the exact delay between frames, but if the wall clock gets adjusted 66441e847feb0e055ecb004802802cea07782ab228Andy McFadden // we won't track it, which means we'll gradually go out of sync with the 67441e847feb0e055ecb004802802cea07782ab228Andy McFadden // times in logcat. 68441e847feb0e055ecb004802802cea07782ab228Andy McFadden mStartMonotonicNsecs = systemTime(CLOCK_MONOTONIC); 69441e847feb0e055ecb004802802cea07782ab228Andy McFadden mStartRealtimeNsecs = systemTime(CLOCK_REALTIME); 70441e847feb0e055ecb004802802cea07782ab228Andy McFadden 717a66622c2c9250ce4ad0091195331ce4cb91a63dAndy McFadden Mutex::Autolock _l(mMutex); 727a66622c2c9250ce4ad0091195331ce4cb91a63dAndy McFadden 73441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Start the thread. Traffic begins immediately. 74441e847feb0e055ecb004802802cea07782ab228Andy McFadden run("overlay"); 75441e847feb0e055ecb004802802cea07782ab228Andy McFadden 76441e847feb0e055ecb004802802cea07782ab228Andy McFadden mState = INIT; 77441e847feb0e055ecb004802802cea07782ab228Andy McFadden while (mState == INIT) { 78441e847feb0e055ecb004802802cea07782ab228Andy McFadden mStartCond.wait(mMutex); 79441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 80441e847feb0e055ecb004802802cea07782ab228Andy McFadden 81441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (mThreadResult != NO_ERROR) { 82441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGE("Failed to start overlay thread: err=%d", mThreadResult); 83441e847feb0e055ecb004802802cea07782ab228Andy McFadden return mThreadResult; 84441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 857a66622c2c9250ce4ad0091195331ce4cb91a63dAndy McFadden assert(mState == RUNNING); 86441e847feb0e055ecb004802802cea07782ab228Andy McFadden 87441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGV("Overlay::start successful"); 88b278f5e70c001391779525fb4d3b024503ba9466Dan Stoza *pBufferProducer = mProducer; 89441e847feb0e055ecb004802802cea07782ab228Andy McFadden return NO_ERROR; 90441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 91441e847feb0e055ecb004802802cea07782ab228Andy McFadden 92441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Overlay::stop() { 93441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGV("Overlay::stop"); 94441e847feb0e055ecb004802802cea07782ab228Andy McFadden Mutex::Autolock _l(mMutex); 95441e847feb0e055ecb004802802cea07782ab228Andy McFadden mState = STOPPING; 96441e847feb0e055ecb004802802cea07782ab228Andy McFadden mEventCond.signal(); 97441e847feb0e055ecb004802802cea07782ab228Andy McFadden return NO_ERROR; 98441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 99441e847feb0e055ecb004802802cea07782ab228Andy McFadden 100441e847feb0e055ecb004802802cea07782ab228Andy McFaddenbool Overlay::threadLoop() { 101441e847feb0e055ecb004802802cea07782ab228Andy McFadden Mutex::Autolock _l(mMutex); 102441e847feb0e055ecb004802802cea07782ab228Andy McFadden 103441e847feb0e055ecb004802802cea07782ab228Andy McFadden mThreadResult = setup_l(); 104441e847feb0e055ecb004802802cea07782ab228Andy McFadden 105441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (mThreadResult != NO_ERROR) { 106441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGW("Aborting overlay thread"); 107441e847feb0e055ecb004802802cea07782ab228Andy McFadden mState = STOPPED; 108441e847feb0e055ecb004802802cea07782ab228Andy McFadden release_l(); 109441e847feb0e055ecb004802802cea07782ab228Andy McFadden mStartCond.broadcast(); 110441e847feb0e055ecb004802802cea07782ab228Andy McFadden return false; 111441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 112441e847feb0e055ecb004802802cea07782ab228Andy McFadden 113441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGV("Overlay thread running"); 114441e847feb0e055ecb004802802cea07782ab228Andy McFadden mState = RUNNING; 115441e847feb0e055ecb004802802cea07782ab228Andy McFadden mStartCond.broadcast(); 116441e847feb0e055ecb004802802cea07782ab228Andy McFadden 117441e847feb0e055ecb004802802cea07782ab228Andy McFadden while (mState == RUNNING) { 118441e847feb0e055ecb004802802cea07782ab228Andy McFadden mEventCond.wait(mMutex); 119441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (mFrameAvailable) { 120441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGV("Awake, frame available"); 121441e847feb0e055ecb004802802cea07782ab228Andy McFadden processFrame_l(); 122441e847feb0e055ecb004802802cea07782ab228Andy McFadden mFrameAvailable = false; 123441e847feb0e055ecb004802802cea07782ab228Andy McFadden } else { 124441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGV("Awake, frame not available"); 125441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 126441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 127441e847feb0e055ecb004802802cea07782ab228Andy McFadden 128441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGV("Overlay thread stopping"); 129441e847feb0e055ecb004802802cea07782ab228Andy McFadden release_l(); 130441e847feb0e055ecb004802802cea07782ab228Andy McFadden mState = STOPPED; 131441e847feb0e055ecb004802802cea07782ab228Andy McFadden return false; // stop 132441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 133441e847feb0e055ecb004802802cea07782ab228Andy McFadden 134441e847feb0e055ecb004802802cea07782ab228Andy McFaddenstatus_t Overlay::setup_l() { 135441e847feb0e055ecb004802802cea07782ab228Andy McFadden status_t err; 136441e847feb0e055ecb004802802cea07782ab228Andy McFadden 137441e847feb0e055ecb004802802cea07782ab228Andy McFadden err = mEglWindow.createWindow(mOutputSurface); 138441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (err != NO_ERROR) { 139441e847feb0e055ecb004802802cea07782ab228Andy McFadden return err; 140441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 141441e847feb0e055ecb004802802cea07782ab228Andy McFadden mEglWindow.makeCurrent(); 142441e847feb0e055ecb004802802cea07782ab228Andy McFadden 143441e847feb0e055ecb004802802cea07782ab228Andy McFadden int width = mEglWindow.getWidth(); 144441e847feb0e055ecb004802802cea07782ab228Andy McFadden int height = mEglWindow.getHeight(); 145441e847feb0e055ecb004802802cea07782ab228Andy McFadden 146441e847feb0e055ecb004802802cea07782ab228Andy McFadden glViewport(0, 0, width, height); 147441e847feb0e055ecb004802802cea07782ab228Andy McFadden glDisable(GL_DEPTH_TEST); 148441e847feb0e055ecb004802802cea07782ab228Andy McFadden glDisable(GL_CULL_FACE); 149441e847feb0e055ecb004802802cea07782ab228Andy McFadden 150441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Shaders for rendering from different types of textures. 151441e847feb0e055ecb004802802cea07782ab228Andy McFadden err = mTexProgram.setup(Program::PROGRAM_TEXTURE_2D); 152441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (err != NO_ERROR) { 153441e847feb0e055ecb004802802cea07782ab228Andy McFadden return err; 154441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 155441e847feb0e055ecb004802802cea07782ab228Andy McFadden err = mExtTexProgram.setup(Program::PROGRAM_EXTERNAL_TEXTURE); 156441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (err != NO_ERROR) { 157441e847feb0e055ecb004802802cea07782ab228Andy McFadden return err; 158441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 159441e847feb0e055ecb004802802cea07782ab228Andy McFadden 160441e847feb0e055ecb004802802cea07782ab228Andy McFadden err = mTextRenderer.loadIntoTexture(); 161441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (err != NO_ERROR) { 162441e847feb0e055ecb004802802cea07782ab228Andy McFadden return err; 163441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 164441e847feb0e055ecb004802802cea07782ab228Andy McFadden mTextRenderer.setScreenSize(width, height); 165441e847feb0e055ecb004802802cea07782ab228Andy McFadden 166441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Input side (buffers from virtual display). 167441e847feb0e055ecb004802802cea07782ab228Andy McFadden glGenTextures(1, &mExtTextureName); 168441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (mExtTextureName == 0) { 169441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGE("glGenTextures failed: %#x", glGetError()); 170441e847feb0e055ecb004802802cea07782ab228Andy McFadden return UNKNOWN_ERROR; 171441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 172441e847feb0e055ecb004802802cea07782ab228Andy McFadden 173b278f5e70c001391779525fb4d3b024503ba9466Dan Stoza sp<IGraphicBufferConsumer> consumer; 174b278f5e70c001391779525fb4d3b024503ba9466Dan Stoza BufferQueue::createBufferQueue(&mProducer, &consumer); 175b278f5e70c001391779525fb4d3b024503ba9466Dan Stoza mGlConsumer = new GLConsumer(consumer, mExtTextureName, 176db2722a319d91a869ebc4dd618edbef43fd5b738Dan Stoza GL_TEXTURE_EXTERNAL_OES, true, false); 177441e847feb0e055ecb004802802cea07782ab228Andy McFadden mGlConsumer->setName(String8("virtual display")); 178441e847feb0e055ecb004802802cea07782ab228Andy McFadden mGlConsumer->setDefaultBufferSize(width, height); 1796e6eaa7ac713ab6606726c3f76a9019ded97f018Pablo Ceballos mProducer->setMaxDequeuedBufferCount(4); 180441e847feb0e055ecb004802802cea07782ab228Andy McFadden mGlConsumer->setConsumerUsageBits(GRALLOC_USAGE_HW_TEXTURE); 181441e847feb0e055ecb004802802cea07782ab228Andy McFadden 182441e847feb0e055ecb004802802cea07782ab228Andy McFadden mGlConsumer->setFrameAvailableListener(this); 183441e847feb0e055ecb004802802cea07782ab228Andy McFadden 184441e847feb0e055ecb004802802cea07782ab228Andy McFadden return NO_ERROR; 185441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 186441e847feb0e055ecb004802802cea07782ab228Andy McFadden 187441e847feb0e055ecb004802802cea07782ab228Andy McFadden 188441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid Overlay::release_l() { 189441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGV("Overlay::release_l"); 190441e847feb0e055ecb004802802cea07782ab228Andy McFadden mOutputSurface.clear(); 191441e847feb0e055ecb004802802cea07782ab228Andy McFadden mGlConsumer.clear(); 192b278f5e70c001391779525fb4d3b024503ba9466Dan Stoza mProducer.clear(); 193441e847feb0e055ecb004802802cea07782ab228Andy McFadden 194441e847feb0e055ecb004802802cea07782ab228Andy McFadden mTexProgram.release(); 195441e847feb0e055ecb004802802cea07782ab228Andy McFadden mExtTexProgram.release(); 196441e847feb0e055ecb004802802cea07782ab228Andy McFadden mEglWindow.release(); 197441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 198441e847feb0e055ecb004802802cea07782ab228Andy McFadden 199441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid Overlay::processFrame_l() { 200441e847feb0e055ecb004802802cea07782ab228Andy McFadden float texMatrix[16]; 201441e847feb0e055ecb004802802cea07782ab228Andy McFadden 202441e847feb0e055ecb004802802cea07782ab228Andy McFadden mGlConsumer->updateTexImage(); 203441e847feb0e055ecb004802802cea07782ab228Andy McFadden mGlConsumer->getTransformMatrix(texMatrix); 204441e847feb0e055ecb004802802cea07782ab228Andy McFadden nsecs_t monotonicNsec = mGlConsumer->getTimestamp(); 205441e847feb0e055ecb004802802cea07782ab228Andy McFadden nsecs_t frameNumber = mGlConsumer->getFrameNumber(); 206441e847feb0e055ecb004802802cea07782ab228Andy McFadden int64_t droppedFrames = 0; 207441e847feb0e055ecb004802802cea07782ab228Andy McFadden 208441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (mLastFrameNumber > 0) { 209441e847feb0e055ecb004802802cea07782ab228Andy McFadden mTotalDroppedFrames += size_t(frameNumber - mLastFrameNumber) - 1; 210441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 211441e847feb0e055ecb004802802cea07782ab228Andy McFadden mLastFrameNumber = frameNumber; 212441e847feb0e055ecb004802802cea07782ab228Andy McFadden 213441e847feb0e055ecb004802802cea07782ab228Andy McFadden mTextRenderer.setProportionalScale(35); 214441e847feb0e055ecb004802802cea07782ab228Andy McFadden 215441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (false) { // DEBUG - full blue background 216441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClearColor(0.0f, 0.0f, 1.0f, 1.0f); 217441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClear(GL_DEPTH_BUFFER_BIT | GL_COLOR_BUFFER_BIT); 218441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 219441e847feb0e055ecb004802802cea07782ab228Andy McFadden 220441e847feb0e055ecb004802802cea07782ab228Andy McFadden int width = mEglWindow.getWidth(); 221441e847feb0e055ecb004802802cea07782ab228Andy McFadden int height = mEglWindow.getHeight(); 222441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (false) { // DEBUG - draw inset 223441e847feb0e055ecb004802802cea07782ab228Andy McFadden mExtTexProgram.blit(mExtTextureName, texMatrix, 224441e847feb0e055ecb004802802cea07782ab228Andy McFadden 100, 100, width-200, height-200); 225441e847feb0e055ecb004802802cea07782ab228Andy McFadden } else { 226441e847feb0e055ecb004802802cea07782ab228Andy McFadden mExtTexProgram.blit(mExtTextureName, texMatrix, 227441e847feb0e055ecb004802802cea07782ab228Andy McFadden 0, 0, width, height); 228441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 229441e847feb0e055ecb004802802cea07782ab228Andy McFadden 230441e847feb0e055ecb004802802cea07782ab228Andy McFadden glEnable(GL_BLEND); 231441e847feb0e055ecb004802802cea07782ab228Andy McFadden glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 232441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (false) { // DEBUG - show entire font bitmap 233441e847feb0e055ecb004802802cea07782ab228Andy McFadden mTexProgram.blit(mTextRenderer.getTextureName(), Program::kIdentity, 234441e847feb0e055ecb004802802cea07782ab228Andy McFadden 100, 100, width-200, height-200); 235441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 236441e847feb0e055ecb004802802cea07782ab228Andy McFadden 237441e847feb0e055ecb004802802cea07782ab228Andy McFadden char textBuf[64]; 238441e847feb0e055ecb004802802cea07782ab228Andy McFadden getTimeString_l(monotonicNsec, textBuf, sizeof(textBuf)); 239884989c67081190ff864419328e9e81506db67caMark Salyzyn String8 timeStr(String8::format("%s f=%" PRId64 " (%zd)", 240441e847feb0e055ecb004802802cea07782ab228Andy McFadden textBuf, frameNumber, mTotalDroppedFrames)); 241441e847feb0e055ecb004802802cea07782ab228Andy McFadden mTextRenderer.drawString(mTexProgram, Program::kIdentity, 0, 0, timeStr); 242441e847feb0e055ecb004802802cea07782ab228Andy McFadden 243441e847feb0e055ecb004802802cea07782ab228Andy McFadden glDisable(GL_BLEND); 244441e847feb0e055ecb004802802cea07782ab228Andy McFadden 245441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (false) { // DEBUG - add red rectangle in lower-left corner 246441e847feb0e055ecb004802802cea07782ab228Andy McFadden glEnable(GL_SCISSOR_TEST); 247441e847feb0e055ecb004802802cea07782ab228Andy McFadden glScissor(0, 0, 200, 200); 248441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClearColor(1.0f, 0.0f, 0.0f, 1.0f); 249441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClear(GL_COLOR_BUFFER_BIT); 250441e847feb0e055ecb004802802cea07782ab228Andy McFadden glDisable(GL_SCISSOR_TEST); 251441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 252441e847feb0e055ecb004802802cea07782ab228Andy McFadden 253441e847feb0e055ecb004802802cea07782ab228Andy McFadden mEglWindow.presentationTime(monotonicNsec); 254441e847feb0e055ecb004802802cea07782ab228Andy McFadden mEglWindow.swapBuffers(); 255441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 256441e847feb0e055ecb004802802cea07782ab228Andy McFadden 257441e847feb0e055ecb004802802cea07782ab228Andy McFaddenvoid Overlay::getTimeString_l(nsecs_t monotonicNsec, char* buf, size_t bufLen) { 258441e847feb0e055ecb004802802cea07782ab228Andy McFadden //const char* format = "%m-%d %T"; // matches log output 259441e847feb0e055ecb004802802cea07782ab228Andy McFadden const char* format = "%T"; 260441e847feb0e055ecb004802802cea07782ab228Andy McFadden struct tm tm; 261441e847feb0e055ecb004802802cea07782ab228Andy McFadden 262441e847feb0e055ecb004802802cea07782ab228Andy McFadden // localtime/strftime is not the fastest way to do this, but a trivial 263441e847feb0e055ecb004802802cea07782ab228Andy McFadden // benchmark suggests that the cost is negligible. 264441e847feb0e055ecb004802802cea07782ab228Andy McFadden int64_t realTime = mStartRealtimeNsecs + 265441e847feb0e055ecb004802802cea07782ab228Andy McFadden (monotonicNsec - mStartMonotonicNsecs); 266441e847feb0e055ecb004802802cea07782ab228Andy McFadden time_t secs = (time_t) (realTime / 1000000000); 267441e847feb0e055ecb004802802cea07782ab228Andy McFadden localtime_r(&secs, &tm); 268441e847feb0e055ecb004802802cea07782ab228Andy McFadden strftime(buf, bufLen, format, &tm); 269441e847feb0e055ecb004802802cea07782ab228Andy McFadden 270441e847feb0e055ecb004802802cea07782ab228Andy McFadden int32_t msec = (int32_t) ((realTime % 1000000000) / 1000000); 271441e847feb0e055ecb004802802cea07782ab228Andy McFadden char tmpBuf[5]; 272441e847feb0e055ecb004802802cea07782ab228Andy McFadden snprintf(tmpBuf, sizeof(tmpBuf), ".%03d", msec); 273441e847feb0e055ecb004802802cea07782ab228Andy McFadden strlcat(buf, tmpBuf, bufLen); 274441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 275441e847feb0e055ecb004802802cea07782ab228Andy McFadden 276441e847feb0e055ecb004802802cea07782ab228Andy McFadden// Callback; executes on arbitrary thread. 27704f101c35eaa90b1f95939afac30674ec1611e6fDan Stozavoid Overlay::onFrameAvailable(const BufferItem& /* item */) { 278441e847feb0e055ecb004802802cea07782ab228Andy McFadden ALOGV("Overlay::onFrameAvailable"); 279441e847feb0e055ecb004802802cea07782ab228Andy McFadden Mutex::Autolock _l(mMutex); 280441e847feb0e055ecb004802802cea07782ab228Andy McFadden mFrameAvailable = true; 281441e847feb0e055ecb004802802cea07782ab228Andy McFadden mEventCond.signal(); 282441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 283441e847feb0e055ecb004802802cea07782ab228Andy McFadden 284441e847feb0e055ecb004802802cea07782ab228Andy McFadden 285441e847feb0e055ecb004802802cea07782ab228Andy McFadden/*static*/ status_t Overlay::drawInfoPage( 286441e847feb0e055ecb004802802cea07782ab228Andy McFadden const sp<IGraphicBufferProducer>& outputSurface) { 287441e847feb0e055ecb004802802cea07782ab228Andy McFadden status_t err; 288441e847feb0e055ecb004802802cea07782ab228Andy McFadden 289441e847feb0e055ecb004802802cea07782ab228Andy McFadden EglWindow window; 290441e847feb0e055ecb004802802cea07782ab228Andy McFadden err = window.createWindow(outputSurface); 291441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (err != NO_ERROR) { 292441e847feb0e055ecb004802802cea07782ab228Andy McFadden return err; 293441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 294441e847feb0e055ecb004802802cea07782ab228Andy McFadden window.makeCurrent(); 295441e847feb0e055ecb004802802cea07782ab228Andy McFadden 296441e847feb0e055ecb004802802cea07782ab228Andy McFadden int width = window.getWidth(); 297441e847feb0e055ecb004802802cea07782ab228Andy McFadden int height = window.getHeight(); 298441e847feb0e055ecb004802802cea07782ab228Andy McFadden glViewport(0, 0, width, height); 299441e847feb0e055ecb004802802cea07782ab228Andy McFadden glDisable(GL_DEPTH_TEST); 300441e847feb0e055ecb004802802cea07782ab228Andy McFadden glDisable(GL_CULL_FACE); 301441e847feb0e055ecb004802802cea07782ab228Andy McFadden 302441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Shaders for rendering. 303441e847feb0e055ecb004802802cea07782ab228Andy McFadden Program texProgram; 304441e847feb0e055ecb004802802cea07782ab228Andy McFadden err = texProgram.setup(Program::PROGRAM_TEXTURE_2D); 305441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (err != NO_ERROR) { 306441e847feb0e055ecb004802802cea07782ab228Andy McFadden return err; 307441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 308441e847feb0e055ecb004802802cea07782ab228Andy McFadden TextRenderer textRenderer; 309441e847feb0e055ecb004802802cea07782ab228Andy McFadden err = textRenderer.loadIntoTexture(); 310441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (err != NO_ERROR) { 311441e847feb0e055ecb004802802cea07782ab228Andy McFadden return err; 312441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 313441e847feb0e055ecb004802802cea07782ab228Andy McFadden textRenderer.setScreenSize(width, height); 314441e847feb0e055ecb004802802cea07782ab228Andy McFadden 315441e847feb0e055ecb004802802cea07782ab228Andy McFadden doDrawInfoPage(window, texProgram, textRenderer); 316441e847feb0e055ecb004802802cea07782ab228Andy McFadden 317441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Destroy the surface. This causes a disconnect. 318441e847feb0e055ecb004802802cea07782ab228Andy McFadden texProgram.release(); 319441e847feb0e055ecb004802802cea07782ab228Andy McFadden window.release(); 320441e847feb0e055ecb004802802cea07782ab228Andy McFadden 321441e847feb0e055ecb004802802cea07782ab228Andy McFadden return NO_ERROR; 322441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 323441e847feb0e055ecb004802802cea07782ab228Andy McFadden 324441e847feb0e055ecb004802802cea07782ab228Andy McFadden/*static*/ void Overlay::doDrawInfoPage(const EglWindow& window, 325441e847feb0e055ecb004802802cea07782ab228Andy McFadden const Program& texProgram, TextRenderer& textRenderer) { 326441e847feb0e055ecb004802802cea07782ab228Andy McFadden const nsecs_t holdTime = 250000000LL; 327441e847feb0e055ecb004802802cea07782ab228Andy McFadden 328441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClearColor(0.0f, 0.0f, 0.0f, 1.0f); 329441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClear(GL_COLOR_BUFFER_BIT); 330441e847feb0e055ecb004802802cea07782ab228Andy McFadden 331441e847feb0e055ecb004802802cea07782ab228Andy McFadden int width = window.getWidth(); 332441e847feb0e055ecb004802802cea07782ab228Andy McFadden int height = window.getHeight(); 333441e847feb0e055ecb004802802cea07782ab228Andy McFadden 334441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Draw a thin border around the screen. Some players, e.g. browser 335441e847feb0e055ecb004802802cea07782ab228Andy McFadden // plugins, make it hard to see where the edges are when the device 336441e847feb0e055ecb004802802cea07782ab228Andy McFadden // is using a black background, so this gives the viewer a frame of 337441e847feb0e055ecb004802802cea07782ab228Andy McFadden // reference. 338441e847feb0e055ecb004802802cea07782ab228Andy McFadden // 339441e847feb0e055ecb004802802cea07782ab228Andy McFadden // This is a clumsy way to do it, but we're only doing it for one frame, 340441e847feb0e055ecb004802802cea07782ab228Andy McFadden // and it's easier than actually drawing lines. 341441e847feb0e055ecb004802802cea07782ab228Andy McFadden const int lineWidth = 4; 342441e847feb0e055ecb004802802cea07782ab228Andy McFadden glEnable(GL_SCISSOR_TEST); 343441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClearColor(0.5f, 0.5f, 0.5f, 1.0f); 344441e847feb0e055ecb004802802cea07782ab228Andy McFadden glScissor(0, 0, width, lineWidth); 345441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClear(GL_COLOR_BUFFER_BIT); 346441e847feb0e055ecb004802802cea07782ab228Andy McFadden glScissor(0, height - lineWidth, width, lineWidth); 347441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClear(GL_COLOR_BUFFER_BIT); 348441e847feb0e055ecb004802802cea07782ab228Andy McFadden glScissor(0, 0, lineWidth, height); 349441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClear(GL_COLOR_BUFFER_BIT); 350441e847feb0e055ecb004802802cea07782ab228Andy McFadden glScissor(width - lineWidth, 0, lineWidth, height); 351441e847feb0e055ecb004802802cea07782ab228Andy McFadden glClear(GL_COLOR_BUFFER_BIT); 352441e847feb0e055ecb004802802cea07782ab228Andy McFadden glDisable(GL_SCISSOR_TEST); 353441e847feb0e055ecb004802802cea07782ab228Andy McFadden 354441e847feb0e055ecb004802802cea07782ab228Andy McFadden //glEnable(GL_BLEND); 355441e847feb0e055ecb004802802cea07782ab228Andy McFadden //glBlendFunc(GL_ONE, GL_ONE_MINUS_SRC_ALPHA); 356441e847feb0e055ecb004802802cea07782ab228Andy McFadden textRenderer.setProportionalScale(30); 357441e847feb0e055ecb004802802cea07782ab228Andy McFadden 358441e847feb0e055ecb004802802cea07782ab228Andy McFadden float xpos = 0; 359441e847feb0e055ecb004802802cea07782ab228Andy McFadden float ypos = 0; 360441e847feb0e055ecb004802802cea07782ab228Andy McFadden ypos = textRenderer.drawWrappedString(texProgram, xpos, ypos, 361441e847feb0e055ecb004802802cea07782ab228Andy McFadden String8::format("Android screenrecord v%d.%d", 362441e847feb0e055ecb004802802cea07782ab228Andy McFadden kVersionMajor, kVersionMinor)); 363441e847feb0e055ecb004802802cea07782ab228Andy McFadden 364441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Show date/time 365441e847feb0e055ecb004802802cea07782ab228Andy McFadden time_t now = time(0); 366441e847feb0e055ecb004802802cea07782ab228Andy McFadden struct tm tm; 367441e847feb0e055ecb004802802cea07782ab228Andy McFadden localtime_r(&now, &tm); 368441e847feb0e055ecb004802802cea07782ab228Andy McFadden char timeBuf[64]; 369441e847feb0e055ecb004802802cea07782ab228Andy McFadden strftime(timeBuf, sizeof(timeBuf), "%a, %d %b %Y %T %z", &tm); 370441e847feb0e055ecb004802802cea07782ab228Andy McFadden String8 header("Started "); 371441e847feb0e055ecb004802802cea07782ab228Andy McFadden header += timeBuf; 372441e847feb0e055ecb004802802cea07782ab228Andy McFadden ypos = textRenderer.drawWrappedString(texProgram, xpos, ypos, header); 373441e847feb0e055ecb004802802cea07782ab228Andy McFadden ypos += 8 * textRenderer.getScale(); // slight padding 374441e847feb0e055ecb004802802cea07782ab228Andy McFadden 375441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Show selected system property values 376441e847feb0e055ecb004802802cea07782ab228Andy McFadden for (int i = 0; i < NELEM(kPropertyNames); i++) { 377441e847feb0e055ecb004802802cea07782ab228Andy McFadden char valueBuf[PROPERTY_VALUE_MAX]; 378441e847feb0e055ecb004802802cea07782ab228Andy McFadden 379441e847feb0e055ecb004802802cea07782ab228Andy McFadden property_get(kPropertyNames[i], valueBuf, ""); 380441e847feb0e055ecb004802802cea07782ab228Andy McFadden if (valueBuf[0] == '\0') { 381441e847feb0e055ecb004802802cea07782ab228Andy McFadden continue; 382441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 383441e847feb0e055ecb004802802cea07782ab228Andy McFadden String8 str(String8::format("%s: [%s]", kPropertyNames[i], valueBuf)); 384441e847feb0e055ecb004802802cea07782ab228Andy McFadden ypos = textRenderer.drawWrappedString(texProgram, xpos, ypos, str); 385441e847feb0e055ecb004802802cea07782ab228Andy McFadden } 386441e847feb0e055ecb004802802cea07782ab228Andy McFadden ypos += 8 * textRenderer.getScale(); // slight padding 387441e847feb0e055ecb004802802cea07782ab228Andy McFadden 388441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Show GL info 389441e847feb0e055ecb004802802cea07782ab228Andy McFadden String8 glStr("OpenGL: "); 390441e847feb0e055ecb004802802cea07782ab228Andy McFadden glStr += (char*) glGetString(GL_VENDOR); 391441e847feb0e055ecb004802802cea07782ab228Andy McFadden glStr += " / "; 392441e847feb0e055ecb004802802cea07782ab228Andy McFadden glStr += (char*) glGetString(GL_RENDERER); 393441e847feb0e055ecb004802802cea07782ab228Andy McFadden glStr += ", "; 394441e847feb0e055ecb004802802cea07782ab228Andy McFadden glStr += (char*) glGetString(GL_VERSION); 395441e847feb0e055ecb004802802cea07782ab228Andy McFadden ypos = textRenderer.drawWrappedString(texProgram, xpos, ypos, glStr); 396441e847feb0e055ecb004802802cea07782ab228Andy McFadden 397441e847feb0e055ecb004802802cea07782ab228Andy McFadden //glDisable(GL_BLEND); 398441e847feb0e055ecb004802802cea07782ab228Andy McFadden 399441e847feb0e055ecb004802802cea07782ab228Andy McFadden // Set a presentation time slightly in the past. This will cause the 400441e847feb0e055ecb004802802cea07782ab228Andy McFadden // player to hold the frame on screen. 401441e847feb0e055ecb004802802cea07782ab228Andy McFadden window.presentationTime(systemTime(CLOCK_MONOTONIC) - holdTime); 402441e847feb0e055ecb004802802cea07782ab228Andy McFadden window.swapBuffers(); 403441e847feb0e055ecb004802802cea07782ab228Andy McFadden} 404