1 /*
2  * Copyright (C) 2010 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 /* 3DMacroscopic implementation */
18 
19 #include "sles_allinclusive.h"
20 
21 
I3DMacroscopic_SetSize(SL3DMacroscopicItf self,SLmillimeter width,SLmillimeter height,SLmillimeter depth)22 static SLresult I3DMacroscopic_SetSize(SL3DMacroscopicItf self,
23     SLmillimeter width, SLmillimeter height, SLmillimeter depth)
24 {
25     SL_ENTER_INTERFACE
26 
27     if (!((0 <= width) && (width <= SL_MILLIMETER_MAX) &&
28         (0 <= height) && (height <= SL_MILLIMETER_MAX) &&
29         (0 <= depth) && (depth <= SL_MILLIMETER_MAX))) {
30         result = SL_RESULT_PARAMETER_INVALID;
31     } else {
32         I3DMacroscopic *thiz = (I3DMacroscopic *) self;
33         interface_lock_exclusive(thiz);
34         thiz->mSize.mWidth = width;
35         thiz->mSize.mHeight = height;
36         thiz->mSize.mDepth = depth;
37         interface_unlock_exclusive(thiz);
38         result = SL_RESULT_SUCCESS;
39     }
40 
41     SL_LEAVE_INTERFACE
42 }
43 
44 
I3DMacroscopic_GetSize(SL3DMacroscopicItf self,SLmillimeter * pWidth,SLmillimeter * pHeight,SLmillimeter * pDepth)45 static SLresult I3DMacroscopic_GetSize(SL3DMacroscopicItf self,
46     SLmillimeter *pWidth, SLmillimeter *pHeight, SLmillimeter *pDepth)
47 {
48     SL_ENTER_INTERFACE
49 
50     if (NULL == pWidth || NULL == pHeight || NULL == pDepth) {
51         result = SL_RESULT_PARAMETER_INVALID;
52     } else {
53         I3DMacroscopic *thiz = (I3DMacroscopic *) self;
54         interface_lock_shared(thiz);
55         SLmillimeter width = thiz->mSize.mWidth;
56         SLmillimeter height = thiz->mSize.mHeight;
57         SLmillimeter depth = thiz->mSize.mDepth;
58         interface_unlock_shared(thiz);
59         *pWidth = width;
60         *pHeight = height;
61         *pDepth = depth;
62         result = SL_RESULT_SUCCESS;
63     }
64 
65     SL_LEAVE_INTERFACE
66 }
67 
68 
I3DMacroscopic_SetOrientationAngles(SL3DMacroscopicItf self,SLmillidegree heading,SLmillidegree pitch,SLmillidegree roll)69 static SLresult I3DMacroscopic_SetOrientationAngles(SL3DMacroscopicItf self,
70     SLmillidegree heading, SLmillidegree pitch, SLmillidegree roll)
71 {
72     SL_ENTER_INTERFACE
73 
74     if (!((-360000 <= heading) && (heading <= 360000) &&
75         (-90000 <= pitch) && (pitch <= 90000) &&
76         (-360000 <= roll) && (roll <= 360000))) {
77         result = SL_RESULT_PARAMETER_INVALID;
78     } else {
79         I3DMacroscopic *thiz = (I3DMacroscopic *) self;
80         interface_lock_exclusive(thiz);
81         thiz->mOrientationAngles.mHeading = heading;
82         thiz->mOrientationAngles.mPitch = pitch;
83         thiz->mOrientationAngles.mRoll = roll;
84         thiz->mOrientationActive = ANGLES_SET_VECTORS_UNKNOWN;
85         thiz->mRotatePending = SL_BOOLEAN_FALSE;
86         // ++thiz->mGeneration;
87         interface_unlock_exclusive(thiz);
88         result = SL_RESULT_SUCCESS;
89     }
90 
91     SL_LEAVE_INTERFACE
92 }
93 
94 
I3DMacroscopic_SetOrientationVectors(SL3DMacroscopicItf self,const SLVec3D * pFront,const SLVec3D * pAbove)95 static SLresult I3DMacroscopic_SetOrientationVectors(SL3DMacroscopicItf self,
96     const SLVec3D *pFront, const SLVec3D *pAbove)
97 {
98     SL_ENTER_INTERFACE
99 
100     if (NULL == pFront || NULL == pAbove) {
101         result = SL_RESULT_PARAMETER_INVALID;
102     } else {
103         I3DMacroscopic *thiz = (I3DMacroscopic *) self;
104         SLVec3D front = *pFront;
105         SLVec3D above = *pAbove;
106         // NTH Check for vectors close to zero or close to parallel
107         interface_lock_exclusive(thiz);
108         thiz->mOrientationVectors.mFront = front;
109         thiz->mOrientationVectors.mAbove = above;
110         thiz->mOrientationVectors.mUp = above; // wrong
111         thiz->mOrientationActive = ANGLES_UNKNOWN_VECTORS_SET;
112         thiz->mRotatePending = SL_BOOLEAN_FALSE;
113         interface_unlock_exclusive(thiz);
114         result = SL_RESULT_SUCCESS;
115     }
116 
117     SL_LEAVE_INTERFACE
118 }
119 
120 
I3DMacroscopic_Rotate(SL3DMacroscopicItf self,SLmillidegree theta,const SLVec3D * pAxis)121 static SLresult I3DMacroscopic_Rotate(SL3DMacroscopicItf self,
122     SLmillidegree theta, const SLVec3D *pAxis)
123 {
124     SL_ENTER_INTERFACE
125 
126     if (!((-360000 <= theta) && (theta <= 360000)) || NULL == pAxis) {
127         result = SL_RESULT_PARAMETER_INVALID;
128     } else {
129         SLVec3D axis = *pAxis;
130         // NTH Check that axis is not (close to) zero vector, length does not matter
131         I3DMacroscopic *thiz = (I3DMacroscopic *) self;
132         interface_lock_exclusive(thiz);
133         while (thiz->mRotatePending)
134             interface_cond_wait(thiz);
135         thiz->mTheta = theta;
136         thiz->mAxis = axis;
137         thiz->mRotatePending = SL_BOOLEAN_TRUE;
138         interface_unlock_exclusive(thiz);
139         result = SL_RESULT_SUCCESS;
140     }
141 
142     SL_LEAVE_INTERFACE
143 }
144 
145 
I3DMacroscopic_GetOrientationVectors(SL3DMacroscopicItf self,SLVec3D * pFront,SLVec3D * pUp)146 static SLresult I3DMacroscopic_GetOrientationVectors(SL3DMacroscopicItf self,
147     SLVec3D *pFront, SLVec3D *pUp)
148 {
149     SL_ENTER_INTERFACE
150 
151     if (NULL == pFront || NULL == pUp) {
152         result = SL_RESULT_PARAMETER_INVALID;
153     } else {
154         I3DMacroscopic *thiz = (I3DMacroscopic *) self;
155         interface_lock_exclusive(thiz);
156         for (;;) {
157             enum AnglesVectorsActive orientationActive = thiz->mOrientationActive;
158             switch (orientationActive) {
159             case ANGLES_COMPUTED_VECTORS_SET:    // not in 1.0.1
160             case ANGLES_REQUESTED_VECTORS_SET:   // not in 1.0.1
161             case ANGLES_UNKNOWN_VECTORS_SET:
162             case ANGLES_SET_VECTORS_COMPUTED:
163                 {
164                 SLVec3D front = thiz->mOrientationVectors.mFront;
165                 SLVec3D up = thiz->mOrientationVectors.mUp;
166                 interface_unlock_exclusive(thiz);
167                 *pFront = front;
168                 *pUp = up;
169                 }
170                 break;
171             case ANGLES_SET_VECTORS_UNKNOWN:
172                 thiz->mOrientationActive = ANGLES_SET_VECTORS_REQUESTED;
173                 FALLTHROUGH_INTENDED;
174             case ANGLES_SET_VECTORS_REQUESTED:
175                 // matched by cond_broadcast in case multiple requesters
176 #if 0
177                 interface_cond_wait(thiz);
178 #else
179                 thiz->mOrientationActive = ANGLES_SET_VECTORS_COMPUTED;
180 #endif
181                 continue;
182             default:
183                 interface_unlock_exclusive(thiz);
184                 assert(SL_BOOLEAN_FALSE);
185                 pFront->x = 0;
186                 pFront->y = 0;
187                 pFront->z = 0;
188                 pUp->x = 0;
189                 pUp->y = 0;
190                 pUp->z = 0;
191                 break;
192             }
193             break;
194         }
195         result = SL_RESULT_SUCCESS;
196     }
197 
198     SL_LEAVE_INTERFACE
199 }
200 
201 
202 static const struct SL3DMacroscopicItf_ I3DMacroscopic_Itf = {
203     I3DMacroscopic_SetSize,
204     I3DMacroscopic_GetSize,
205     I3DMacroscopic_SetOrientationAngles,
206     I3DMacroscopic_SetOrientationVectors,
207     I3DMacroscopic_Rotate,
208     I3DMacroscopic_GetOrientationVectors
209 };
210 
I3DMacroscopic_init(void * self)211 void I3DMacroscopic_init(void *self)
212 {
213     I3DMacroscopic *thiz = (I3DMacroscopic *) self;
214     thiz->mItf = &I3DMacroscopic_Itf;
215     thiz->mSize.mWidth = 0;
216     thiz->mSize.mHeight = 0;
217     thiz->mSize.mDepth = 0;
218     thiz->mOrientationAngles.mHeading = 0;
219     thiz->mOrientationAngles.mPitch = 0;
220     thiz->mOrientationAngles.mRoll = 0;
221     memset(&thiz->mOrientationVectors, 0x55, sizeof(thiz->mOrientationVectors));
222     thiz->mOrientationVectors.mFront.x = 0;
223     thiz->mOrientationVectors.mFront.y = 0;
224     thiz->mOrientationVectors.mFront.z = -1000;
225     thiz->mOrientationVectors.mUp.x = 0;
226     thiz->mOrientationVectors.mUp.y = 1000;
227     thiz->mOrientationVectors.mUp.z = 0;
228     thiz->mOrientationVectors.mAbove.x = 0;
229     thiz->mOrientationVectors.mAbove.y = 0;
230     thiz->mOrientationVectors.mAbove.z = 0;
231     thiz->mOrientationActive = ANGLES_SET_VECTORS_COMPUTED;
232     thiz->mTheta = 0x55555555;
233     thiz->mAxis.x = 0x55555555;
234     thiz->mAxis.y = 0x55555555;
235     thiz->mAxis.z = 0x55555555;
236     thiz->mRotatePending = SL_BOOLEAN_FALSE;
237 }
238