1 /*
2  * Copyright (c) 2022 Huawei Device Co., Ltd.
3  * Licensed under the Apache License, Version 2.0 (the "License");
4  * you may not use this file except in compliance with the License.
5  * You may obtain a copy of the License at
6  *
7  *     http://www.apache.org/licenses/LICENSE-2.0
8  *
9  * Unless required by applicable law or agreed to in writing, software
10  * distributed under the License is distributed on an "AS IS" BASIS,
11  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  * See the License for the specific language governing permissions and
13  * limitations under the License.
14  */
15 #include "thread_private_data_ctl.h"
16 
17 #include "EGL/egl_wrapper_entry.h"
18 #include "wrapper_log.h"
19 namespace OHOS {
20 constexpr int32_t PTHREAD_KEY_T_NOT_INITIALIZED = -1;
21 pthread_key_t ThreadPrivateDataCtl::key_ = PTHREAD_KEY_T_NOT_INITIALIZED;
22 pthread_key_t ThreadPrivateDataCtl::tableKey_ = PTHREAD_KEY_T_NOT_INITIALIZED;
23 pthread_once_t ThreadPrivateDataCtl::onceCtl_ = PTHREAD_ONCE_INIT;
24 
KeyInit()25 void ThreadPrivateDataCtl::KeyInit()
26 {
27     if (pthread_key_create(&key_, nullptr) != 0) {
28         WLOGE("Failed to create thread key.");
29         return;
30     }
31     if (pthread_key_create(&tableKey_, nullptr) != 0) {
32         WLOGE("Failed to create thread key.");
33         return;
34     }
35     WLOGD("pthread_key_create. key = %{public}d", key_);
36 }
37 
ValidateKey()38 void ThreadPrivateDataCtl::ValidateKey()
39 {
40     pthread_once(&onceCtl_, KeyInit);
41 }
42 
GetPrivateData()43 ThreadPrivateData* ThreadPrivateDataCtl::GetPrivateData()
44 {
45     ValidateKey();
46     ThreadPrivateData *data = static_cast<ThreadPrivateData *>(pthread_getspecific(key_));
47     if (data == nullptr) {
48         data = new ThreadPrivateData;
49         pthread_setspecific(key_, data);
50     }
51     return data;
52 }
53 
ClearPrivateData()54 void ThreadPrivateDataCtl::ClearPrivateData()
55 {
56     if (key_ != static_cast<pthread_key_t>(PTHREAD_KEY_T_NOT_INITIALIZED)) {
57         ThreadPrivateData *data = static_cast<ThreadPrivateData *>(pthread_getspecific(key_));
58         if (data) {
59             pthread_setspecific(key_, nullptr);
60             delete data;
61         }
62     }
63     if (tableKey_ != static_cast<pthread_key_t>(PTHREAD_KEY_T_NOT_INITIALIZED)) {
64         pthread_setspecific(tableKey_, nullptr);
65     }
66 }
67 
68 #ifdef EGL_ERROR_ENABLE
ClearError()69 void ThreadPrivateDataCtl::ClearError()
70 {
71     OHOS::EglGetErrorImpl();
72 }
73 #endif
74 
GetError()75 EGLint ThreadPrivateDataCtl::GetError()
76 {
77     if (key_ == static_cast<pthread_key_t>(PTHREAD_KEY_T_NOT_INITIALIZED)) {
78         return EGL_SUCCESS;
79     }
80 
81     ThreadPrivateData *data = static_cast<ThreadPrivateData *>(pthread_getspecific(key_));
82     if (!data) {
83         return EGL_SUCCESS;
84     }
85 
86     EGLint error = data->error;
87     data->error = EGL_SUCCESS;
88 
89     return error;
90 }
91 
SetError(EGLint error)92 void ThreadPrivateDataCtl::SetError(EGLint error)
93 {
94     ValidateKey();
95     ThreadPrivateData *data = GetPrivateData();
96     if (data->error != error) {
97         WLOGW("ThreadPrivateDataCtl::SetError error = %{public}d.", error);
98         data->error = error;
99     }
100 }
101 
SetContext(EGLContext ctx)102 void ThreadPrivateDataCtl::SetContext(EGLContext ctx)
103 {
104     ValidateKey();
105     GetPrivateData()->ctx = ctx;
106 }
107 
GetContext()108 EGLContext ThreadPrivateDataCtl::GetContext()
109 {
110     if (key_ == static_cast<pthread_key_t>(PTHREAD_KEY_T_NOT_INITIALIZED)) {
111         return EGL_NO_CONTEXT;
112     }
113 
114     ThreadPrivateData *data = static_cast<ThreadPrivateData *>(pthread_getspecific(key_));
115     if (!data) {
116         return EGL_NO_CONTEXT;
117     }
118 
119     return data->ctx;
120 }
121 
SetGlHookTable(GlHookTable * table)122 void ThreadPrivateDataCtl::SetGlHookTable(GlHookTable *table)
123 {
124     ValidateKey();
125     pthread_setspecific(tableKey_, table);
126 }
127 
GetGlHookTable()128 GlHookTable *ThreadPrivateDataCtl::GetGlHookTable()
129 {
130     if (tableKey_ == static_cast<pthread_key_t>(PTHREAD_KEY_T_NOT_INITIALIZED)) {
131         return nullptr;
132     }
133     return static_cast<GlHookTable *>(pthread_getspecific(tableKey_));
134 }
135 
136 } // namespace OHOS
137