blob: f3ed790181ebc7ed75cfd21f277ecbfe0eab9910 [file] [log] [blame]
Mathias Agopian076b1cc2009-04-10 14:24:30 -07001/*
2 * Copyright (C) 2008 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 <stdlib.h>
18#include <stdio.h>
19#include <stdint.h>
20#include <unistd.h>
21#include <fcntl.h>
22#include <errno.h>
23#include <math.h>
24#include <sys/types.h>
25#include <sys/stat.h>
26#include <sys/ioctl.h>
27
28#include <cutils/log.h>
29#include <cutils/properties.h>
30
31#include <utils/MemoryDealer.h>
32#include <utils/MemoryBase.h>
33#include <utils/MemoryHeapPmem.h>
34#include <utils/MemoryHeapBase.h>
35
36#include "GPUHardware/GPUHardware.h"
37#include "SurfaceFlinger.h"
38#include "VRamHeap.h"
39
40#if HAVE_ANDROID_OS
41#include <linux/android_pmem.h>
42#endif
43
44
45namespace android {
46
47// ---------------------------------------------------------------------------
48
49/*
50 * Amount of memory we reserve for surface, per client in PMEM
51 * (PMEM is used for 2D acceleration)
52 * 8 MB of address space per client should be enough.
53 */
54static const int PMEM_SIZE = int(8 * 1024 * 1024);
55
56int SurfaceHeapManager::global_pmem_heap = 0;
57
58// ---------------------------------------------------------------------------
59
60SurfaceHeapManager::SurfaceHeapManager(const sp<SurfaceFlinger>& flinger,
61 size_t clientHeapSize)
62 : mFlinger(flinger), mClientHeapSize(clientHeapSize)
63{
64 SurfaceHeapManager::global_pmem_heap = 1;
65}
66
67SurfaceHeapManager::~SurfaceHeapManager()
68{
69}
70
71void SurfaceHeapManager::onFirstRef()
72{
73 if (global_pmem_heap) {
74 const char* device = "/dev/pmem";
75 mPMemHeap = new PMemHeap(device, PMEM_SIZE);
76 if (mPMemHeap->base() == MAP_FAILED) {
77 mPMemHeap.clear();
78 global_pmem_heap = 0;
79 }
80 }
81}
82
83sp<MemoryDealer> SurfaceHeapManager::createHeap(
84 uint32_t flags,
85 pid_t client_pid,
86 const sp<MemoryDealer>& defaultAllocator)
87{
88 sp<MemoryDealer> dealer;
89
90 if (flags & ISurfaceComposer::eGPU) {
91 // don't grant GPU memory if GPU is disabled
92 char value[PROPERTY_VALUE_MAX];
93 property_get("debug.egl.hw", value, "1");
94 if (atoi(value) == 0) {
95 flags &= ~ISurfaceComposer::eGPU;
96 }
97 }
98
99 if (flags & ISurfaceComposer::eGPU) {
100 // FIXME: this is msm7201A specific, where gpu surfaces may not be secure
101 if (!(flags & ISurfaceComposer::eSecure)) {
102 // if GPU doesn't work, we try eHardware
103 flags |= ISurfaceComposer::eHardware;
104 // asked for GPU memory, try that first
105 dealer = mFlinger->getGPU()->request(client_pid);
106 }
107 }
108
109 if (dealer == NULL) {
110 if (defaultAllocator != NULL)
111 // if a default allocator is given, use that
112 dealer = defaultAllocator;
113 }
114
115 if (dealer == NULL) {
116 // always try h/w accelerated memory first
117 if (global_pmem_heap) {
118 const sp<PMemHeap>& heap(mPMemHeap);
119 if (dealer == NULL && heap != NULL) {
120 dealer = new MemoryDealer(
121 heap->createClientHeap(),
122 heap->getAllocator());
123 }
124 }
125 }
126
127 if (dealer == NULL) {
128 // return the ashmem allocator (software rendering)
129 dealer = new MemoryDealer(mClientHeapSize, 0, "SFNativeHeap");
130 }
131 return dealer;
132}
133
134sp<SimpleBestFitAllocator> SurfaceHeapManager::getAllocator(int type) const
135{
136 Mutex::Autolock _l(mLock);
137 sp<SimpleBestFitAllocator> allocator;
138
139 // this is only used for debugging
140 switch (type) {
141 case NATIVE_MEMORY_TYPE_PMEM:
142 if (mPMemHeap != 0) {
143 allocator = mPMemHeap->getAllocator();
144 }
145 break;
146 }
147 return allocator;
148}
149
150// ---------------------------------------------------------------------------
151
152PMemHeap::PMemHeap(const char* const device, size_t size, size_t reserved)
153 : MemoryHeapBase(device, size)
154{
155 //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID());
156 if (base() != MAP_FAILED) {
157 //LOGD("%s, %u bytes", device, virtualSize());
158 if (reserved == 0)
159 reserved = virtualSize();
160 mAllocator = new SimpleBestFitAllocator(reserved);
161 }
162}
163
164PMemHeap::~PMemHeap() {
165 //LOGD("%s, %p, mFD=%d", __PRETTY_FUNCTION__, this, heapID());
166}
167
168sp<MemoryHeapPmem> PMemHeap::createClientHeap() {
169 sp<MemoryHeapBase> parentHeap(this);
170 return new MemoryHeapPmem(parentHeap);
171}
172
173// ---------------------------------------------------------------------------
174}; // namespace android