Home | History | Annotate | Download | only in hwui
      1 /*
      2  * Copyright (C) 2016 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 "utils/StringUtils.h"
     18 
     19 #include <GpuMemoryTracker.h>
     20 #include <cutils/compiler.h>
     21 #include <utils/Trace.h>
     22 #include <array>
     23 #include <sstream>
     24 #include <unordered_set>
     25 #include <vector>
     26 
     27 namespace android {
     28 namespace uirenderer {
     29 
     30 pthread_t gGpuThread = 0;
     31 
     32 #define NUM_TYPES static_cast<int>(GpuObjectType::TypeCount)
     33 
     34 const char* TYPE_NAMES[] = {
     35         "Texture", "OffscreenBuffer", "Layer",
     36 };
     37 
     38 struct TypeStats {
     39     int totalSize = 0;
     40     int count = 0;
     41 };
     42 
     43 static std::array<TypeStats, NUM_TYPES> gObjectStats;
     44 static std::unordered_set<GpuMemoryTracker*> gObjectSet;
     45 
     46 void GpuMemoryTracker::notifySizeChanged(int newSize) {
     47     int delta = newSize - mSize;
     48     mSize = newSize;
     49     gObjectStats[static_cast<int>(mType)].totalSize += delta;
     50 }
     51 
     52 void GpuMemoryTracker::startTrackingObject() {
     53     auto result = gObjectSet.insert(this);
     54     LOG_ALWAYS_FATAL_IF(!result.second,
     55                         "startTrackingObject() on %p failed, already being tracked!", this);
     56     gObjectStats[static_cast<int>(mType)].count++;
     57 }
     58 
     59 void GpuMemoryTracker::stopTrackingObject() {
     60     size_t removed = gObjectSet.erase(this);
     61     LOG_ALWAYS_FATAL_IF(removed != 1, "stopTrackingObject removed %zd, is %p not being tracked?",
     62                         removed, this);
     63     gObjectStats[static_cast<int>(mType)].count--;
     64 }
     65 
     66 void GpuMemoryTracker::onGpuContextCreated() {
     67     LOG_ALWAYS_FATAL_IF(gGpuThread != 0,
     68                         "We already have a gpu thread? "
     69                         "current = %lu, gpu thread = %lu",
     70                         pthread_self(), gGpuThread);
     71     gGpuThread = pthread_self();
     72 }
     73 
     74 void GpuMemoryTracker::onGpuContextDestroyed() {
     75     gGpuThread = 0;
     76     if (CC_UNLIKELY(gObjectSet.size() > 0)) {
     77         std::stringstream os;
     78         dump(os);
     79         ALOGE("%s", os.str().c_str());
     80         LOG_ALWAYS_FATAL("Leaked %zd GPU objects!", gObjectSet.size());
     81     }
     82 }
     83 
     84 void GpuMemoryTracker::dump() {
     85     std::stringstream strout;
     86     dump(strout);
     87     ALOGD("%s", strout.str().c_str());
     88 }
     89 
     90 void GpuMemoryTracker::dump(std::ostream& stream) {
     91     for (int type = 0; type < NUM_TYPES; type++) {
     92         const TypeStats& stats = gObjectStats[type];
     93         stream << TYPE_NAMES[type];
     94         stream << " is using " << SizePrinter{stats.totalSize};
     95         stream << ", count = " << stats.count;
     96         stream << std::endl;
     97     }
     98 }
     99 
    100 int GpuMemoryTracker::getInstanceCount(GpuObjectType type) {
    101     return gObjectStats[static_cast<int>(type)].count;
    102 }
    103 
    104 int GpuMemoryTracker::getTotalSize(GpuObjectType type) {
    105     return gObjectStats[static_cast<int>(type)].totalSize;
    106 }
    107 
    108 void GpuMemoryTracker::onFrameCompleted() {
    109     if (ATRACE_ENABLED()) {
    110         char buf[128];
    111         for (int type = 0; type < NUM_TYPES; type++) {
    112             snprintf(buf, 128, "hwui_%s", TYPE_NAMES[type]);
    113             const TypeStats& stats = gObjectStats[type];
    114             ATRACE_INT(buf, stats.totalSize);
    115             snprintf(buf, 128, "hwui_%s_count", TYPE_NAMES[type]);
    116             ATRACE_INT(buf, stats.count);
    117         }
    118     }
    119 }
    120 
    121 }  // namespace uirenderer
    122 }  // namespace android;
    123