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