oculus2
changeset 2:0984fa94b490
rendering almost works
author | John Tsiombikas <nuclear@member.fsf.org> |
---|---|
date | Tue, 26 Aug 2014 08:14:09 +0300 |
parents | dbbb4ec77df5 |
children | 096b18432ba7 |
files | oculus2.sln oculus2.vcxproj oculus2.vcxproj.filters src/main.c |
diffstat | 4 files changed, 281 insertions(+), 20 deletions(-) [+] |
line diff
1.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 1.2 +++ b/oculus2.sln Tue Aug 26 08:14:09 2014 +0300 1.3 @@ -0,0 +1,22 @@ 1.4 + 1.5 +Microsoft Visual Studio Solution File, Format Version 12.00 1.6 +# Visual Studio 2013 1.7 +VisualStudioVersion = 12.0.30501.0 1.8 +MinimumVisualStudioVersion = 10.0.40219.1 1.9 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "oculus2", "oculus2.vcxproj", "{7A2D6788-B885-455C-8DE6-46D5C7313207}" 1.10 +EndProject 1.11 +Global 1.12 + GlobalSection(SolutionConfigurationPlatforms) = preSolution 1.13 + Debug|Win32 = Debug|Win32 1.14 + Release|Win32 = Release|Win32 1.15 + EndGlobalSection 1.16 + GlobalSection(ProjectConfigurationPlatforms) = postSolution 1.17 + {7A2D6788-B885-455C-8DE6-46D5C7313207}.Debug|Win32.ActiveCfg = Debug|Win32 1.18 + {7A2D6788-B885-455C-8DE6-46D5C7313207}.Debug|Win32.Build.0 = Debug|Win32 1.19 + {7A2D6788-B885-455C-8DE6-46D5C7313207}.Release|Win32.ActiveCfg = Release|Win32 1.20 + {7A2D6788-B885-455C-8DE6-46D5C7313207}.Release|Win32.Build.0 = Release|Win32 1.21 + EndGlobalSection 1.22 + GlobalSection(SolutionProperties) = preSolution 1.23 + HideSolutionNode = FALSE 1.24 + EndGlobalSection 1.25 +EndGlobal
2.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 2.2 +++ b/oculus2.vcxproj Tue Aug 26 08:14:09 2014 +0300 2.3 @@ -0,0 +1,88 @@ 2.4 +<?xml version="1.0" encoding="utf-8"?> 2.5 +<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 2.6 + <ItemGroup Label="ProjectConfigurations"> 2.7 + <ProjectConfiguration Include="Debug|Win32"> 2.8 + <Configuration>Debug</Configuration> 2.9 + <Platform>Win32</Platform> 2.10 + </ProjectConfiguration> 2.11 + <ProjectConfiguration Include="Release|Win32"> 2.12 + <Configuration>Release</Configuration> 2.13 + <Platform>Win32</Platform> 2.14 + </ProjectConfiguration> 2.15 + </ItemGroup> 2.16 + <PropertyGroup Label="Globals"> 2.17 + <ProjectGuid>{7A2D6788-B885-455C-8DE6-46D5C7313207}</ProjectGuid> 2.18 + <Keyword>Win32Proj</Keyword> 2.19 + <RootNamespace>oculus2</RootNamespace> 2.20 + </PropertyGroup> 2.21 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> 2.22 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> 2.23 + <ConfigurationType>Application</ConfigurationType> 2.24 + <UseDebugLibraries>true</UseDebugLibraries> 2.25 + <PlatformToolset>v120</PlatformToolset> 2.26 + <CharacterSet>Unicode</CharacterSet> 2.27 + </PropertyGroup> 2.28 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> 2.29 + <ConfigurationType>Application</ConfigurationType> 2.30 + <UseDebugLibraries>false</UseDebugLibraries> 2.31 + <PlatformToolset>v120</PlatformToolset> 2.32 + <WholeProgramOptimization>true</WholeProgramOptimization> 2.33 + <CharacterSet>Unicode</CharacterSet> 2.34 + </PropertyGroup> 2.35 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> 2.36 + <ImportGroup Label="ExtensionSettings"> 2.37 + </ImportGroup> 2.38 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 2.39 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 2.40 + </ImportGroup> 2.41 + <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 2.42 + <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> 2.43 + </ImportGroup> 2.44 + <PropertyGroup Label="UserMacros" /> 2.45 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 2.46 + <LinkIncremental>true</LinkIncremental> 2.47 + </PropertyGroup> 2.48 + <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 2.49 + <LinkIncremental>false</LinkIncremental> 2.50 + </PropertyGroup> 2.51 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'"> 2.52 + <ClCompile> 2.53 + <PrecompiledHeader> 2.54 + </PrecompiledHeader> 2.55 + <WarningLevel>Level3</WarningLevel> 2.56 + <Optimization>Disabled</Optimization> 2.57 + <PreprocessorDefinitions>WIN32;_DEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> 2.58 + <DisableSpecificWarnings>4305;4244</DisableSpecificWarnings> 2.59 + </ClCompile> 2.60 + <Link> 2.61 + <SubSystem>Console</SubSystem> 2.62 + <GenerateDebugInformation>true</GenerateDebugInformation> 2.63 + <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;sdl2.lib;sdl2main.lib;opengl32.lib;glew32.lib;libovrd.lib;winmm.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> 2.64 + </Link> 2.65 + </ItemDefinitionGroup> 2.66 + <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> 2.67 + <ClCompile> 2.68 + <WarningLevel>Level3</WarningLevel> 2.69 + <PrecompiledHeader> 2.70 + </PrecompiledHeader> 2.71 + <Optimization>MaxSpeed</Optimization> 2.72 + <FunctionLevelLinking>true</FunctionLevelLinking> 2.73 + <IntrinsicFunctions>true</IntrinsicFunctions> 2.74 + <PreprocessorDefinitions>WIN32;NDEBUG;_CONSOLE;_LIB;%(PreprocessorDefinitions)</PreprocessorDefinitions> 2.75 + <DisableSpecificWarnings>4305;4244</DisableSpecificWarnings> 2.76 + </ClCompile> 2.77 + <Link> 2.78 + <SubSystem>Console</SubSystem> 2.79 + <GenerateDebugInformation>true</GenerateDebugInformation> 2.80 + <EnableCOMDATFolding>true</EnableCOMDATFolding> 2.81 + <OptimizeReferences>true</OptimizeReferences> 2.82 + <AdditionalDependencies>kernel32.lib;user32.lib;gdi32.lib;winspool.lib;comdlg32.lib;advapi32.lib;shell32.lib;ole32.lib;oleaut32.lib;uuid.lib;odbc32.lib;odbccp32.lib;sdl2.lib;sdl2main.lib;opengl32.lib;glew32.lib;libovr.lib;winmm.lib;ws2_32.lib;%(AdditionalDependencies)</AdditionalDependencies> 2.83 + </Link> 2.84 + </ItemDefinitionGroup> 2.85 + <ItemGroup> 2.86 + <ClCompile Include="src\main.c" /> 2.87 + </ItemGroup> 2.88 + <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> 2.89 + <ImportGroup Label="ExtensionTargets"> 2.90 + </ImportGroup> 2.91 +</Project> 2.92 \ No newline at end of file
3.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 3.2 +++ b/oculus2.vcxproj.filters Tue Aug 26 08:14:09 2014 +0300 3.3 @@ -0,0 +1,14 @@ 3.4 +<?xml version="1.0" encoding="utf-8"?> 3.5 +<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> 3.6 + <ItemGroup> 3.7 + <Filter Include="src"> 3.8 + <UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> 3.9 + <Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx;h;inl</Extensions> 3.10 + </Filter> 3.11 + </ItemGroup> 3.12 + <ItemGroup> 3.13 + <ClCompile Include="src\main.c"> 3.14 + <Filter>src</Filter> 3.15 + </ClCompile> 3.16 + </ItemGroup> 3.17 +</Project> 3.18 \ No newline at end of file
4.1 --- a/src/main.c Tue Aug 26 02:56:45 2014 +0300 4.2 +++ b/src/main.c Tue Aug 26 08:14:09 2014 +0300 4.3 @@ -1,14 +1,24 @@ 4.4 #include <stdio.h> 4.5 #include <stdlib.h> 4.6 +#include <assert.h> 4.7 #include <SDL2/SDL.h> 4.8 #include <GL/glew.h> 4.9 4.10 +#ifdef WIN32 4.11 +#define OVR_OS_WIN32 4.12 +#endif 4.13 +#ifdef __APPLE__ 4.14 +#define OVR_OS_MAC 4.15 +#endif 4.16 + 4.17 #include <OVR_CAPI.h> 4.18 #include <OVR_CAPI_GL.h> 4.19 4.20 -int init(); 4.21 -void cleanup(); 4.22 -void display(); 4.23 +int init(void); 4.24 +void cleanup(void); 4.25 +void display(void); 4.26 +void draw_scene(void); 4.27 +void draw_box(float xsz, float ysz, float zsz, float norm_sign); 4.28 void update_rtarg(int width, int height); 4.29 int handle_event(SDL_Event *ev); 4.30 int key_event(int key, int state); 4.31 @@ -19,6 +29,7 @@ 4.32 4.33 static SDL_Window *win; 4.34 static SDL_GLContext ctx; 4.35 +static int win_width, win_height; 4.36 4.37 static unsigned int fbo, fb_tex, fb_depth; 4.38 static int fb_width, fb_height; 4.39 @@ -26,6 +37,8 @@ 4.40 4.41 static ovrHmd hmd; 4.42 static ovrSizei eyeres[2]; 4.43 +static ovrEyeRenderDesc eye_rdesc[2]; 4.44 +static ovrGLTexture fb_ovr_tex[2]; 4.45 4.46 4.47 int main(void) 4.48 @@ -52,12 +65,11 @@ 4.49 } 4.50 4.51 4.52 -int init() 4.53 +int init(void) 4.54 { 4.55 - int x, y; 4.56 + int i, x, y; 4.57 unsigned int flags, dcaps; 4.58 union ovrGLConfig glcfg; 4.59 - ovrEyeRenderDesc eye_rdesc[2]; 4.60 4.61 // this must be called before any OpenGL init according to the docs 4.62 ovr_Initialize(); 4.63 @@ -65,7 +77,7 @@ 4.64 SDL_Init(SDL_INIT_VIDEO | SDL_INIT_TIMER); 4.65 4.66 x = y = SDL_WINDOWPOS_UNDEFINED; 4.67 - flags = SDL_WINDOW_OPENGL | SDL_WINDOW_RESIZABLE; 4.68 + flags = SDL_WINDOW_OPENGL; 4.69 if(!(win = SDL_CreateWindow("simple oculus example", x, y, 1280, 800, flags))) { 4.70 fprintf(stderr, "failed to create window\n"); 4.71 return -1; 4.72 @@ -79,23 +91,37 @@ 4.73 4.74 if(!(hmd = ovrHmd_Create(0))) { 4.75 fprintf(stderr, "failed to open Oculus HMD, falling back to virtual debug HMD\n"); 4.76 - if(!(hmd = ovrHmd_CreateDebug())) { 4.77 + if(!(hmd = ovrHmd_CreateDebug(ovrHmd_DK2))) { 4.78 fprintf(stderr, "failed to create virtual debug HMD\n"); 4.79 return -1; 4.80 } 4.81 } 4.82 printf("initialized HMD: %s - %s\n", hmd->Manufacturer, hmd->ProductName); 4.83 4.84 - SDL_SetWindowSize(hmd->Resolution.w, hmd->Resolution.h); 4.85 + SDL_SetWindowSize(win, hmd->Resolution.w, hmd->Resolution.h); 4.86 4.87 ovrHmd_ConfigureTracking(hmd, 0xffffffff, 0); 4.88 eyeres[0] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Left, hmd->DefaultEyeFov[0], 1.0); 4.89 eyeres[1] = ovrHmd_GetFovTextureSize(hmd, ovrEye_Right, hmd->DefaultEyeFov[1], 1.0); 4.90 4.91 - fb_width = eyeres[0].w + eyres[1].w; 4.92 + SDL_GetWindowSize(win, &win_width, &win_height); 4.93 + 4.94 + fb_width = eyeres[0].w + eyeres[1].w; 4.95 fb_height = eyeres[0].h > eyeres[1].h ? eyeres[0].h : eyeres[1].h; 4.96 update_rtarg(fb_width, fb_height); 4.97 4.98 + for(i=0; i<2; i++) { 4.99 + fb_ovr_tex[i].OGL.Header.API = ovrRenderAPI_OpenGL; 4.100 + fb_ovr_tex[i].OGL.Header.TextureSize.w = fb_tex_width; 4.101 + fb_ovr_tex[i].OGL.Header.TextureSize.h = fb_tex_height; 4.102 + fb_ovr_tex[i].OGL.Header.RenderViewport.Pos.y = 0; 4.103 + fb_ovr_tex[i].OGL.Header.RenderViewport.Size.w = fb_width / 2.0; 4.104 + fb_ovr_tex[i].OGL.Header.RenderViewport.Size.h = fb_height; 4.105 + fb_ovr_tex[i].OGL.TexId = fb_tex; 4.106 + } 4.107 + fb_ovr_tex[0].OGL.Header.RenderViewport.Pos.x = 0; 4.108 + fb_ovr_tex[1].OGL.Header.RenderViewport.Pos.x = fb_width / 2.0; 4.109 + 4.110 memset(&glcfg, 0, sizeof glcfg); 4.111 glcfg.OGL.Header.API = ovrRenderAPI_OpenGL; 4.112 glcfg.OGL.Header.RTSize = hmd->Resolution; 4.113 @@ -104,19 +130,22 @@ 4.114 if(hmd->HmdCaps & ovrHmdCap_ExtendDesktop) { 4.115 printf("running in \"extended desktop\" mode\n"); 4.116 } else { 4.117 +#ifdef WIN32 4.118 + void *sys_win = GetActiveWindow(); 4.119 + glcfg.OGL.Window = sys_win; 4.120 + glcfg.OGL.DC = wglGetCurrentDC(); 4.121 + ovrHmd_AttachToWindow(hmd, sys_win, 0, 0); 4.122 +#endif 4.123 printf("running in \"direct-hmd\" mode\n"); 4.124 -#ifdef WIN32 4.125 - ovrHmd_AttachToWindow(hmd, GetActiveWindow(), 0, 0); 4.126 -#endif 4.127 } 4.128 - ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCaps_DynamicPrediction); 4.129 + ovrHmd_SetEnabledCaps(hmd, ovrHmdCap_LowPersistence | ovrHmdCap_DynamicPrediction); 4.130 4.131 - dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWrap; 4.132 + dcaps = ovrDistortionCap_Chromatic | ovrDistortionCap_Vignette | ovrDistortionCap_TimeWarp; 4.133 if(!ovrHmd_ConfigureRendering(hmd, &glcfg.Config, dcaps, hmd->DefaultEyeFov, eye_rdesc)) { 4.134 fprintf(stderr, "failed to configure distortion renderer\n"); 4.135 } 4.136 4.137 - ovrhmd_EnableHSWDisplaySDKRender(hmd, 0); 4.138 + /* ovrhmd_EnableHSWDisplaySDKRender(hmd, 0); */ 4.139 4.140 4.141 glEnable(GL_DEPTH_TEST); 4.142 @@ -124,12 +153,12 @@ 4.143 glEnable(GL_LIGHTING); 4.144 glEnable(GL_LIGHT0); 4.145 4.146 - glClearColor(0.05, 0.05, 0.05, 1); 4.147 + glClearColor(0.5, 0.05, 0.05, 1); 4.148 4.149 return 0; 4.150 } 4.151 4.152 -void cleanup() 4.153 +void cleanup(void) 4.154 { 4.155 if(hmd) { 4.156 ovrHmd_Destroy(hmd); 4.157 @@ -139,11 +168,108 @@ 4.158 SDL_Quit(); 4.159 } 4.160 4.161 -void display() 4.162 +void display(void) 4.163 { 4.164 + int i; 4.165 + ovrMatrix4f proj; 4.166 + ovrPosef pose[2]; 4.167 + 4.168 + ovrHmd_BeginFrame(hmd, 0); 4.169 + 4.170 + glBindFramebuffer(GL_FRAMEBUFFER, fbo); 4.171 glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT); 4.172 4.173 - SDL_GL_SwapWindow(win); 4.174 + /* for each eye ... */ 4.175 + for(i=0; i<2; i++) { 4.176 + int eye = hmd->EyeRenderOrder[i]; 4.177 + 4.178 + /* vport0(0, 0, width/2, height), vport1(width/2, 0, width/2, height) */ 4.179 + glViewport(eye == 0 ? 0 : fb_width / 2, 0, fb_width / 2, fb_height); 4.180 + 4.181 + proj = ovrMatrix4f_Projection(hmd->DefaultEyeFov[eye], 0.5, 500.0, 1); 4.182 + glMatrixMode(GL_PROJECTION); 4.183 + glLoadMatrixf(proj.M[0]); 4.184 + 4.185 + pose[eye] = ovrHmd_GetEyePose(hmd, eye); 4.186 + glMatrixMode(GL_MODELVIEW); 4.187 + /* TODO: get HMD orientation data and use them */ 4.188 + glTranslatef(0, -ovrHmd_GetFloat(hmd, OVR_KEY_EYE_HEIGHT, 1.65), 0); 4.189 + 4.190 + draw_scene(); 4.191 + } 4.192 + 4.193 + glBindFramebuffer(GL_FRAMEBUFFER, 0); 4.194 + glViewport(0, 0, win_width, win_height); 4.195 + 4.196 + ovrHmd_EndFrame(hmd, pose, &fb_ovr_tex[0].Texture); 4.197 + 4.198 + assert(glGetError() == GL_NO_ERROR); 4.199 +} 4.200 + 4.201 +void draw_scene(void) 4.202 +{ 4.203 + int i; 4.204 + float lpos[] = {0, 5, 0, 1}; 4.205 + glLightfv(GL_LIGHT0, GL_POSITION, lpos); 4.206 + 4.207 + glTranslatef(0, 5, 0); 4.208 + draw_box(20, 10, 20, -1.0); 4.209 + 4.210 + for(i=0; i<4; i++) { 4.211 + glPushMatrix(); 4.212 + if(i & 1) { 4.213 + glTranslatef(0, 0, i & 2 ? 7.5 : -7.5); 4.214 + } else { 4.215 + glTranslatef(i & 2 ? 7.5 : -7.5, 0, 0); 4.216 + } 4.217 + draw_box(3, 0, 3, 1.0); 4.218 + glPopMatrix(); 4.219 + } 4.220 +} 4.221 + 4.222 +void draw_box(float xsz, float ysz, float zsz, float norm_sign) 4.223 +{ 4.224 + glMatrixMode(GL_MODELVIEW); 4.225 + glScalef(xsz * 0.5, ysz * 0.5, zsz * 0.5); 4.226 + 4.227 + if(norm_sign < 0.0) { 4.228 + glFrontFace(GL_CW); 4.229 + } 4.230 + 4.231 + glBegin(GL_QUADS); 4.232 + glNormal3f(0, 0, 1 * norm_sign); 4.233 + glTexCoord2f(0, 0); glVertex3f(-1, -1, 1); 4.234 + glTexCoord2f(1, 0); glVertex3f(1, -1, 1); 4.235 + glTexCoord2f(1, 1); glVertex3f(1, 1, 1); 4.236 + glTexCoord2f(0, 1); glVertex3f(-1, 1, 1); 4.237 + glNormal3f(1 * norm_sign, 0, 0); 4.238 + glTexCoord2f(0, 0); glVertex3f(1, -1, 1); 4.239 + glTexCoord2f(1, 0); glVertex3f(1, -1, -1); 4.240 + glTexCoord2f(1, 1); glVertex3f(1, 1, -1); 4.241 + glTexCoord2f(0, 1); glVertex3f(1, 1, 1); 4.242 + glNormal3f(0, 0, -1 * norm_sign); 4.243 + glTexCoord2f(0, 0); glVertex3f(1, -1, -1); 4.244 + glTexCoord2f(1, 0); glVertex3f(-1, -1, -1); 4.245 + glTexCoord2f(1, 1); glVertex3f(-1, 1, -1); 4.246 + glTexCoord2f(0, 1); glVertex3f(1, 1, -1); 4.247 + glNormal3f(-1 * norm_sign, 0, 0); 4.248 + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 4.249 + glTexCoord2f(1, 0); glVertex3f(-1, -1, 1); 4.250 + glTexCoord2f(1, 1); glVertex3f(-1, 1, 1); 4.251 + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); 4.252 + glNormal3f(0, 1 * norm_sign, 0); 4.253 + glTexCoord2f(0, 0); glVertex3f(-1, 1, 1); 4.254 + glTexCoord2f(1, 0); glVertex3f(1, 1, 1); 4.255 + glTexCoord2f(1, 1); glVertex3f(1, 1, -1); 4.256 + glTexCoord2f(0, 1); glVertex3f(-1, 1, -1); 4.257 + glNormal3f(0, -1 * norm_sign, 0); 4.258 + glTexCoord2f(0, 0); glVertex3f(-1, -1, -1); 4.259 + glTexCoord2f(1, 0); glVertex3f(1, -1, -1); 4.260 + glTexCoord2f(1, 1); glVertex3f(1, -1, 1); 4.261 + glTexCoord2f(0, 1); glVertex3f(-1, -1, 1); 4.262 + glEnd(); 4.263 + 4.264 + glFrontFace(GL_CCW); 4.265 } 4.266 4.267 void update_rtarg(int width, int height) 4.268 @@ -210,3 +336,14 @@ 4.269 } 4.270 return 0; 4.271 } 4.272 + 4.273 +unsigned int next_pow2(unsigned int x) 4.274 +{ 4.275 + x -= 1; 4.276 + x |= x >> 1; 4.277 + x |= x >> 2; 4.278 + x |= x >> 4; 4.279 + x |= x >> 8; 4.280 + x |= x >> 16; 4.281 + return x + 1; 4.282 +} 4.283 \ No newline at end of file