github.com/racerxdl/gonx@v0.0.0-20210103083128-c5afc43bcbd2/services/display/igbp.go (about) 1 package display 2 3 import ( 4 "fmt" 5 "github.com/racerxdl/gonx/internal" 6 "github.com/racerxdl/gonx/nx/graphics" 7 "github.com/racerxdl/gonx/nx/nxerrors" 8 "github.com/racerxdl/gonx/services/vi" 9 "unsafe" 10 ) 11 12 const interfaceToken = "android.gui.IGraphicBufferProducer" 13 const ( 14 REQUEST_BUFFER = 0x1 15 SET_BUFFER_COUNT = 0x2 16 DEQUEUE_BUFFER = 0x3 17 DETACH_BUFFER = 0x4 18 DETACH_NEXT_BUFFER = 0x5 19 ATTACH_BUFFER = 0x6 20 QUEUE_BUFFER = 0x7 21 CANCEL_BUFFER = 0x8 22 QUERY = 0x9 23 CONNECT = 0xA 24 DISCONNECT = 0xB 25 ALLOCATE_BUFFERS = 0xD 26 SET_PREALLOCATED_BUFFER = 0xE 27 ) 28 29 type DisconnectMode int 30 31 const ( 32 DisconnectAPI DisconnectMode = 0 33 DisconnectAllLocal DisconnectMode = 1 34 ) 35 36 func IGBPDisconnect(igbp vi.IGBP, api int, mode DisconnectMode) (status int, err error) { 37 if debugDisplay { 38 fmt.Printf("IGBPDisconnect(%d, %d, %d)\n", igbp.IgbpBinder.Handle, api, mode) 39 } 40 p := &vi.Parcel{} 41 42 p.WriteInterfaceToken(interfaceToken) 43 p.WriteU32(uint32(api)) 44 p.WriteU32(uint32(mode)) 45 46 response, err := vi.BinderTransactParcel(igbp.IgbpBinder, DISCONNECT, 0, p) 47 if err != nil { 48 return 0, err 49 } 50 51 if response.Remaining() < 4 { 52 return 0, nxerrors.ParcelDataUnderrun 53 } 54 55 status = int(response.ReadU32()) 56 57 return status, nil 58 } 59 60 func IGBPConnect(igbp vi.IGBP, api int, producerControlledByApp bool) (status int, qbo *QueueBufferOutput, err error) { 61 if debugDisplay { 62 fmt.Printf("IGBPConnect(%d, %d, %t)\n", igbp.IgbpBinder.Handle, api, producerControlledByApp) 63 } 64 p := &vi.Parcel{} 65 66 p.WriteInterfaceToken(interfaceToken) 67 p.WriteU32(0) // IProducerListener is null 68 p.WriteU32(uint32(api)) 69 70 producerControlledByAppInt := uint32(0) 71 if producerControlledByApp { 72 producerControlledByAppInt = 1 73 } 74 75 p.WriteU32(producerControlledByAppInt) 76 77 response, err := vi.BinderTransactParcel(igbp.IgbpBinder, CONNECT, 0, p) 78 if err != nil { 79 return 0, nil, err 80 } 81 82 qbo, err = UnflattenQueueBufferOutput(response) 83 if err != nil { 84 return 0, nil, err 85 } 86 87 if response.Remaining() < 4 { 88 return 0, nil, nxerrors.ParcelDataUnderrun 89 } 90 91 status = int(response.ReadU32()) 92 93 return status, qbo, nil 94 } 95 96 func IGBPRequestBuffer(igbp vi.IGBP, slot uint32) (status uint32, gb *GraphicBuffer, err error) { 97 if debugDisplay { 98 fmt.Printf("IGBPRequestBuffer(%d, %d)\n", igbp.IgbpBinder.Handle, slot) 99 } 100 p := &vi.Parcel{} 101 p.WriteInterfaceToken(interfaceToken) 102 p.WriteU32(slot) 103 104 response, err := vi.BinderTransactParcel(igbp.IgbpBinder, REQUEST_BUFFER, 0, p) 105 if err != nil { 106 return 0, nil, err 107 } 108 109 nonNull := response.ReadU32() != 0 110 if nonNull { 111 length := response.ReadU32() 112 if length != 0x16c { 113 return 0, nil, nxerrors.DisplayGraphicBufferLengthMismatch 114 } 115 _ = response.ReadU32() // PixelBufferOffset 116 gbBuff := response.ReadInPlace(0x16c) 117 gb = &GraphicBuffer{} 118 internal.Memcpy(unsafe.Pointer(gb), unsafe.Pointer(&gbBuff[0]), 0x16c) 119 } 120 121 status = response.ReadU32() 122 123 return status, gb, err 124 } 125 126 func IGBPSetPreallocatedBuffer(igbp vi.IGBP, slot int, gb *GraphicBuffer) error { 127 if debugDisplay { 128 fmt.Printf("IGBPSetPreallocatedBuffer(%d, %d, %p)\n", igbp.IgbpBinder.Handle, slot, gb) 129 } 130 p := &vi.Parcel{} 131 p.WriteInterfaceToken(interfaceToken) 132 p.WriteU32(uint32(slot)) 133 p.WriteU32(1) // Has Input 134 135 err := gb.Flatten(p) 136 if err != nil { 137 return err 138 } 139 140 _, err = vi.BinderTransactParcel(igbp.IgbpBinder, SET_PREALLOCATED_BUFFER, 0, p) 141 return err 142 } 143 144 func IGBPDequeueBuffer(igbp vi.IGBP, width, height uint32, pixelFormat graphics.PixelFormat, usage uint32, getFrameTimestamps bool) (status, slot uint32, fence Fence, outTimestamps *FrameEventHistoryDelta, err error) { 145 if debugDisplay { 146 fmt.Printf("IGBPDequeueBuffer(%d, %d, %d, %d, %d, %t)\n", igbp.IgbpBinder.Handle, width, height, pixelFormat, usage, getFrameTimestamps) 147 } 148 if getFrameTimestamps { 149 return status, slot, fence, outTimestamps, nxerrors.NotImplemented 150 } 151 var response *vi.Parcel 152 153 p := &vi.Parcel{} 154 p.WriteInterfaceToken(interfaceToken) 155 p.WriteU32(0) // async 156 p.WriteU32(width) 157 p.WriteU32(height) 158 p.WriteU32(uint32(pixelFormat)) 159 p.WriteU32(usage) 160 161 response, err = vi.BinderTransactParcel(igbp.IgbpBinder, DEQUEUE_BUFFER, 0, p) 162 if err != nil { 163 return status, slot, fence, outTimestamps, err 164 } 165 166 slot = response.ReadU32() 167 hasFence := response.ReadU32() > 0 168 169 if hasFence { 170 fence, err = UnflattenFence(response) 171 if err != nil { 172 return status, slot, fence, outTimestamps, err 173 } 174 } 175 176 status = response.ReadU32() 177 178 return status, slot, fence, outTimestamps, nil 179 } 180 181 func IGBPQueueBuffer(igbp vi.IGBP, slot int, qbi *QueueBufferInput) (qbo *QueueBufferOutput, status int, err error) { 182 if debugDisplay { 183 fmt.Printf("IGBPQueueBuffer(%d, %d, %p)\n", igbp.IgbpBinder.Handle, slot, qbi) 184 } 185 p := &vi.Parcel{} 186 p.WriteInterfaceToken(interfaceToken) 187 p.WriteU32(uint32(slot)) 188 qbi.Flatten(p) 189 190 resp, err := vi.BinderTransactParcel(igbp.IgbpBinder, QUEUE_BUFFER, 0, p) 191 if err != nil { 192 return nil, 0, err 193 } 194 195 qbo, err = UnflattenQueueBufferOutput(resp) 196 if err != nil { 197 return nil, 0, err 198 } 199 200 status = int(resp.ReadU32()) 201 202 return qbo, status, nil 203 }