github.com/graybobo/golang.org-package-offline-cache@v0.0.0-20200626051047-6608995c132f/x/mobile/gl/dll_windows.go (about) 1 // Copyright 2015 The Go Authors. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package gl 6 7 import ( 8 "archive/tar" 9 "compress/gzip" 10 "fmt" 11 "io" 12 "io/ioutil" 13 "log" 14 "net/http" 15 "os" 16 "path/filepath" 17 "runtime" 18 ) 19 20 var debug = log.New(ioutil.Discard, "gl: ", log.LstdFlags) 21 22 func downloadDLLs() (path string, err error) { 23 url := "https://dl.google.com/go/mobile/angle-dd5c5b-" + runtime.GOARCH + ".tgz" 24 debug.Printf("downloading %s", url) 25 resp, err := http.Get(url) 26 if err != nil { 27 return "", fmt.Errorf("gl: %v", err) 28 } 29 defer func() { 30 err2 := resp.Body.Close() 31 if err == nil && err2 != nil { 32 err = fmt.Errorf("gl: error reading body from %v: %v", url, err2) 33 } 34 }() 35 if resp.StatusCode != http.StatusOK { 36 err := fmt.Errorf("gl: error fetching %v, status: %v", url, resp.Status) 37 return "", err 38 } 39 40 r, err := gzip.NewReader(resp.Body) 41 if err != nil { 42 return "", fmt.Errorf("gl: error reading gzip from %v: %v", url, err) 43 } 44 tr := tar.NewReader(r) 45 var bytesGLESv2, bytesEGL []byte 46 for { 47 header, err := tr.Next() 48 if err == io.EOF { 49 break 50 } 51 if err != nil { 52 return "", fmt.Errorf("gl: error reading tar from %v: %v", url, err) 53 } 54 switch header.Name { 55 case "angle-" + runtime.GOARCH + "/libglesv2.dll": 56 bytesGLESv2, err = ioutil.ReadAll(tr) 57 case "angle-" + runtime.GOARCH + "/libegl.dll": 58 bytesEGL, err = ioutil.ReadAll(tr) 59 default: // skip 60 } 61 if err != nil { 62 return "", fmt.Errorf("gl: error reading %v from %v: %v", header.Name, url, err) 63 } 64 } 65 if len(bytesGLESv2) == 0 || len(bytesEGL) == 0 { 66 return "", fmt.Errorf("gl: did not find both DLLs in %v", url) 67 } 68 69 writeDLLs := func(path string) error { 70 if err := ioutil.WriteFile(filepath.Join(path, "libglesv2.dll"), bytesGLESv2, 0755); err != nil { 71 return fmt.Errorf("gl: cannot install ANGLE: %v", err) 72 } 73 if err := ioutil.WriteFile(filepath.Join(path, "libegl.dll"), bytesEGL, 0755); err != nil { 74 return fmt.Errorf("gl: cannot install ANGLE: %v", err) 75 } 76 return nil 77 } 78 79 // First, we attempt to install these DLLs in LOCALAPPDATA/Shiny. 80 // 81 // Traditionally we would use the system32 directory, but it is 82 // no longer writable by normal programs. 83 os.MkdirAll(appdataPath(), 0775) 84 if err := writeDLLs(appdataPath()); err == nil { 85 return appdataPath(), nil 86 } 87 debug.Printf("DLLs could not be written to %s", appdataPath()) 88 89 // Second, install in GOPATH/pkg if it exists. 90 gopath := os.Getenv("GOPATH") 91 gopathpkg := filepath.Join(gopath, "pkg") 92 if _, err := os.Stat(gopathpkg); err == nil && gopath != "" { 93 if err := writeDLLs(gopathpkg); err == nil { 94 return gopathpkg, nil 95 } 96 } 97 debug.Printf("DLLs could not be written to GOPATH") 98 99 // Third, pick a temporary directory. 100 tmp := os.TempDir() 101 if err := writeDLLs(tmp); err != nil { 102 return "", fmt.Errorf("gl: unable to install ANGLE DLLs: %v", err) 103 } 104 return tmp, nil 105 } 106 107 func appdataPath() string { 108 return filepath.Join(os.Getenv("LOCALAPPDATA"), "GoGL", runtime.GOARCH) 109 } 110 111 func findDLLs() (err error) { 112 load := func(path string) (bool, error) { 113 if path != "" { 114 LibGLESv2.Name = filepath.Join(path, filepath.Base(LibGLESv2.Name)) 115 LibEGL.Name = filepath.Join(path, filepath.Base(LibEGL.Name)) 116 } 117 if err := LibGLESv2.Load(); err == nil { 118 if err := LibEGL.Load(); err != nil { 119 return false, fmt.Errorf("gl: loaded libglesv2 but not libegl: %v", err) 120 } 121 if path == "" { 122 debug.Printf("DLLs found") 123 } else { 124 debug.Printf("DLLs found in: %q", path) 125 } 126 return true, nil 127 } 128 return false, nil 129 } 130 131 // Look in the system directory. 132 if ok, err := load(""); ok || err != nil { 133 return err 134 } 135 136 // Look in the AppData directory. 137 if ok, err := load(appdataPath()); ok || err != nil { 138 return err 139 } 140 141 // TODO: Look for a Chrome installation. 142 143 // Look in GOPATH/pkg. 144 if ok, err := load(filepath.Join(os.Getenv("GOPATH"), "pkg")); ok || err != nil { 145 return err 146 } 147 148 // Look in temporary directory. 149 if ok, err := load(os.TempDir()); ok || err != nil { 150 return err 151 } 152 153 // Download the DLL binary. 154 path, err := downloadDLLs() 155 if err != nil { 156 return err 157 } 158 debug.Printf("DLLs written to %s", path) 159 if ok, err := load(path); !ok || err != nil { 160 return fmt.Errorf("gl: unable to load ANGLE after installation: %v", err) 161 } 162 return nil 163 }