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  }