1 /*
2  * Copyright (C) 2015 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 #ifndef ANDROID_DRM_FRAMEBUFFER_
18 #define ANDROID_DRM_FRAMEBUFFER_
19 
20 #include <stdint.h>
21 
22 #include <sync/sync.h>
23 
24 #include <ui/GraphicBuffer.h>
25 
26 namespace android {
27 
28 struct DrmFramebuffer {
DrmFramebufferDrmFramebuffer29   DrmFramebuffer() : release_fence_fd_(-1) {
30   }
31 
~DrmFramebufferDrmFramebuffer32   ~DrmFramebuffer() {
33     if (release_fence_fd() >= 0)
34       close(release_fence_fd());
35   }
36 
is_validDrmFramebuffer37   bool is_valid() {
38     return buffer_ != NULL;
39   }
40 
bufferDrmFramebuffer41   sp<GraphicBuffer> buffer() {
42     return buffer_;
43   }
44 
release_fence_fdDrmFramebuffer45   int release_fence_fd() {
46     return release_fence_fd_;
47   }
48 
set_release_fence_fdDrmFramebuffer49   void set_release_fence_fd(int fd) {
50     if (release_fence_fd_ >= 0)
51       close(release_fence_fd_);
52     release_fence_fd_ = fd;
53   }
54 
AllocateDrmFramebuffer55   bool Allocate(uint32_t w, uint32_t h) {
56     if (is_valid()) {
57       if (buffer_->getWidth() == w && buffer_->getHeight() == h)
58         return true;
59 
60       if (release_fence_fd_ >= 0) {
61         if (sync_wait(release_fence_fd_, kReleaseWaitTimeoutMs) != 0) {
62           ALOGE("Wait for release fence failed\n");
63           return false;
64         }
65       }
66       Clear();
67     }
68     buffer_ = new GraphicBuffer(w, h, PIXEL_FORMAT_RGBA_8888,
69                                 GRALLOC_USAGE_HW_FB | GRALLOC_USAGE_HW_RENDER |
70                                     GRALLOC_USAGE_HW_COMPOSER);
71     release_fence_fd_ = -1;
72     return is_valid();
73   }
74 
ClearDrmFramebuffer75   void Clear() {
76     if (!is_valid())
77       return;
78 
79     if (release_fence_fd_ >= 0) {
80       close(release_fence_fd_);
81       release_fence_fd_ = -1;
82     }
83 
84     buffer_.clear();
85   }
86 
WaitReleasedDrmFramebuffer87   int WaitReleased(int timeout_milliseconds) {
88     if (!is_valid())
89       return 0;
90     if (release_fence_fd_ < 0)
91       return 0;
92 
93     int ret = sync_wait(release_fence_fd_, timeout_milliseconds);
94     return ret;
95   }
96 
97   // Somewhat arbitrarily chosen, but wanted to stay below 3000ms, which is the
98   // system timeout
99   static const int kReleaseWaitTimeoutMs = 1500;
100 
101  private:
102   sp<GraphicBuffer> buffer_;
103   int release_fence_fd_;
104 };
105 }
106 
107 #endif  // ANDROID_DRM_FRAMEBUFFER_
108