func New() (*Renderer, error) { r := &Renderer{ RenderExec: make(chan func() bool, 1024), LoaderExec: make(chan func(), 1024), renderComplete: make(chan struct{}, 8), wantFree: make(chan struct{}, 1), clock: clock.New(), } // MSAA is enabled by default. r.msaa.enabled = true // Initialize r.render now. r.render = gl.New() r.render.SetBatching(false) if !r.render.AtLeastVersion(2, 0) { return nil, ErrInvalidVersion } // Initialize r.loader now. r.loader = gl.New() r.loader.SetBatching(false) // Note: we don't need r.ctx.Lock() here because no other goroutines // can be using r.ctx yet since we haven't returned from New(). // Find the renderer's precision. var redBits, greenBits, blueBits, alphaBits, depthBits, stencilBits int32 r.render.GetIntegerv(gl.RED_BITS, &redBits) r.render.GetIntegerv(gl.GREEN_BITS, &greenBits) r.render.GetIntegerv(gl.BLUE_BITS, &blueBits) r.render.GetIntegerv(gl.ALPHA_BITS, &alphaBits) r.render.GetIntegerv(gl.DEPTH_BITS, &depthBits) r.render.GetIntegerv(gl.STENCIL_BITS, &stencilBits) r.render.Execute() r.precision.RedBits = uint8(redBits) r.precision.GreenBits = uint8(greenBits) r.precision.BlueBits = uint8(blueBits) r.precision.AlphaBits = uint8(alphaBits) r.precision.DepthBits = uint8(depthBits) r.precision.StencilBits = uint8(stencilBits) // Query whether we have the GL_ARB_framebuffer_object. r.glArbFramebufferObject = r.render.Extension("GL_ARB_framebuffer_object") // Query whether we have the GL_ARB_occlusion_query. r.glArbOcclusionQuery = r.render.Extension("GL_ARB_occlusion_query") // Query whether we have the GL_ARB_multisample extension. r.glArbMultisample = r.render.Extension("GL_ARB_multisample") if r.glArbMultisample { // Query the number of samples and sample buffers we have, if any. r.render.GetIntegerv(gl.SAMPLES, &r.samples) r.render.GetIntegerv(gl.SAMPLE_BUFFERS, &r.sampleBuffers) r.render.Execute() // Needed because glGetIntegerv must execute now. r.precision.Samples = int(r.samples) } // Store GPU info. var maxTextureSize, maxVaryingFloats, maxVertexInputs, maxFragmentInputs, occlusionQueryBits int32 r.render.GetIntegerv(gl.MAX_TEXTURE_SIZE, &maxTextureSize) r.render.GetIntegerv(gl.MAX_VARYING_FLOATS, &maxVaryingFloats) r.render.GetIntegerv(gl.MAX_VERTEX_UNIFORM_COMPONENTS, &maxVertexInputs) r.render.GetIntegerv(gl.MAX_FRAGMENT_UNIFORM_COMPONENTS, &maxFragmentInputs) if r.glArbOcclusionQuery { r.render.GetQueryiv(gl.SAMPLES_PASSED, gl.QUERY_COUNTER_BITS, &occlusionQueryBits) } r.render.Execute() r.gpuInfo.MaxTextureSize = int(maxTextureSize) r.gpuInfo.GLSLMaxVaryingFloats = int(maxVaryingFloats) r.gpuInfo.GLSLMaxVertexInputs = int(maxVertexInputs) r.gpuInfo.GLSLMaxFragmentInputs = int(maxFragmentInputs) r.gpuInfo.GLExtensions = r.render.Extensions() r.gpuInfo.AlphaToCoverage = r.glArbMultisample && r.samples > 0 && r.sampleBuffers > 0 r.gpuInfo.Name = gl.String(r.render.GetString(gl.RENDERER)) r.gpuInfo.Vendor = gl.String(r.render.GetString(gl.VENDOR)) r.gpuInfo.GLMajor, r.gpuInfo.GLMinor, _ = r.render.Version() r.gpuInfo.GLSLMajor, r.gpuInfo.GLSLMinor, _ = r.render.ShaderVersion() r.gpuInfo.OcclusionQuery = r.glArbOcclusionQuery && occlusionQueryBits > 0 r.gpuInfo.OcclusionQueryBits = int(occlusionQueryBits) // Grab the current renderer bounds (opengl viewport). var viewport [4]int32 r.render.GetIntegerv(gl.VIEWPORT, &viewport[0]) r.render.Execute() r.bounds.rect = image.Rect(0, 0, int(viewport[2]), int(viewport[3])) // Update scissor rectangle. r.stateScissor(r.bounds.rect) // Grab the number of texture compression formats. var numFormats int32 r.render.GetIntegerv(gl.NUM_COMPRESSED_TEXTURE_FORMATS, &numFormats) r.render.Execute() // Needed because glGetIntegerv must execute now. // Store the slice of texture compression formats. if numFormats > 0 { r.compressedTextureFormats = make([]int32, numFormats) r.render.GetIntegerv(gl.COMPRESSED_TEXTURE_FORMATS, &r.compressedTextureFormats[0]) r.render.Execute() // Needed because glGetIntegerv must execute now. } return r, nil }
// Nil returns a renderer that does not actually render anything. func Nil() Renderer { r := new(nilRenderer) r.msaa.enabled = true r.clock = clock.New() return r }